// 构造从 x 向外递减的数列(每人至少 1) privatelongcountApple(int x, int len) { if (x >= len) { longfirst= x - len; longlast= x - 1; return (first + last) * len / 2; } else { longfull= (long)(x - 1 + 1) * (x - 1) / 2; longones= len - (x - 1); return full + ones; } }
下面是实现代码:
classSolution { publicintmaxApples(int n, int m, int k) { intleft= k - 1; intright= n - k; intans=1; // 注意这里x直接从2开始 for (intx=2; x <= m; x++) { longtotal= getApple(x, left, right); if (total <= m) { ans++; } else { break; } } return ans; }
publiclonggetApple(int x, int left, int right) { return countApple(x, left) + countApple(x, right) + x; }
publiclongcountApple(int x, int len) { if(x >= len) { longfirst= x - len; longend= x - 1; // 满足要求就是等差数列求和 return (first + end) * len / 2; } else { // 否则就是两部分相加 longpart1= (long) (1 + x - 1) * (x - 1) / 2; longpart2= len - (x - 1); return part1 + part2; } } }
可以发现,我们是从 x = 2 即两个苹果开始一个一个累加的,最终在(1, m)中找到满足要求的数,这显然是可以通过使用二分查找来优化的,下面给出完整的二分实现代码。
四、完整代码
classSolution { publicintmaxApples(int n, int m, int k) { intleft= k - 1; intright= n - k; intans=1; // 使用二分优化 intlow=1; inthigh= m; while (low <= high) { intmid= low + (right - low) / 2; longtotal= getApple(mid, left, right); if (total <= m) { // 满足条件将mid赋给ans同时将mid变大尝试更多的分法 ans = mid; low = mid + 1; } else { high = mid - 1; } } return ans; }
publiclonggetApple(int x, int left, int right) { return countApple(x, left) + countApple(x, right) + x; }
publiclongcountApple(int x, int len) { if(x >= len) { longfirst= x - len; longend= x - 1; // 满足要求就是等差数列求和 return (first + end) * len / 2; } else { // 否则就是两部分相加 longpart1= (long) (1 + x - 1) * (x - 1) / 2; longpart2= len - (x - 1); return part1 + part2; } } }