题解 | 华华给月月准备礼物
华华给月月准备礼物
https://www.nowcoder.com/practice/9963334321e64e61a397b262708e4f65
import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static boolean canGetKSticks(int x, int N, int K, int[] lens) {
// 如果 x=0,避免除零错误
if (x == 0) return true;
long total = 0; // 使用 long 防止溢出
for (int i = 0; i < N; i++) {
total += lens[i] / x;
if (total >= K) {
return true; // 提前返回
}
}
return total >= K;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int K = sc.nextInt();
int[] lens = new int[N];
long sum = 0;
for (int i = 0; i < N; i++) {
lens[i] = sc.nextInt();
sum += lens[i];
}
// 如果所有木棍总长度都小于 K,最多只能得到长度为 0 的木棍
if (sum < K) {
System.out.println(0);
return;
}
// 二分查找最大长度
int left = 0;
int right = 0;
// 找到最大木棍长度
for (int i = 0; i < N; i++) {
right = Math.max(right, lens[i]);
}
int answer = 0;
// 标准的二分查找模板
while (left <= right) {
int mid = left + (right - left) / 2;
if (mid == 0) {
// 如果 mid=0,检查能否得到至少 K 段
// 实际上,如果 K=0 或者 sum>=K,长度为 0 总是可以的
if (K == 0) {
answer = 0;
left = mid + 1;
} else if (sum >= K) {
answer = 0;
left = mid + 1;
} else {
right = mid - 1;
}
continue;
}
if (canGetKSticks(mid, N, K, lens)) {
answer = mid; // 记录当前可行的答案
left = mid + 1; // 尝试更大的长度
} else {
right = mid - 1; // 尝试更小的长度
}
}
System.out.println(answer);
}
}
- 二分查找模板:使用 while (left <= right) 的标准模板,确保找到最大可行解。
- 边界情况处理:当所有木棍总长度小于 K 时,无法得到 K 段木棍,输出 0。处理 mid=0 的情况,避免除零错误。
- 性能优化:使用 long 类型防止整数溢出。在 canGetKSticks 方法中提前返回,减少不必要的计算。
- 变量名改进:使用更清晰的命名 canGetKSticks

