1011. 在 D 天内送达包裹的能力
传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。
传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。
返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。
思路
阅读了几遍题解,终于明白。这个题难在想不到用二分去解决。通常我们的二分都是直接使用,这里进行了一个转化。值得思考
1.这里的二分是运输能力上的二分法。因此,上限是所有包裹的重量和(一天之内运输完),下限是包裹重量的最大值(一天运输一个包裹)。
2.当我们知道运输能力的范围的时候(一个递增序列),那么在这个递增序列上求出一个符合我们要求的值,这个时候问题就转换成了二分法。
3.我们在运输能力上进行二分,寻找某个运输能力为x,使得D天可以运输完成。那么当求得天数<D,说明我们选择的运输能力过大,应该往区间左侧寻找。当求得天数>D,说明我们选择的运输能力过小,应该往区间右侧寻找。
4.求运输能力的对应天数时,用贪心算法。
5.至于缩减区间的,有三种可能:
- 等于D,因为存在不同的运输能力,但是运输天数都为D,要求最小值,所以砍掉右侧区间
- 小于D,说明现在运输能力过大,砍掉右侧区间
- 大于D,现在选的运输能力过小,砍掉
综上,right = mid, left = mid+1;
完整代码
public int shipWithinDays(int[] weights, int D) {
int left = 0;
int right = 0;
for(int i = 0; i < weights.length; i++){
right += weights[i];
left = Math.max(left, weights[i]);
}
while(left < right){
int mid = (right + left) / 2;
int needDay = 1;
int curWeight = 0;
for(int i = 0; i < weights.length; i++){
if(curWeight + weights[i] > mid){
needDay++;
curWeight = 0;
}
curWeight += weights[i];
}
if(needDay <= D){
right = mid;
}else{
left = mid + 1;
}
}
return left;
}
938. 二叉搜索树的范围和
思路
完整代码
因为是二叉搜索树,所以当某结点小于区间的时候那么它的左子树一定小于该范围,应该从右边搜索,反之
int ans = 0;
public int rangeSumBST(TreeNode root, int low, int high) {
dfs(root, low, high);
return ans;
}
public void dfs(TreeNode root, int L, int R){
if(root == null){
return;
}
if(L <= root.val && root.val <= R) {
ans += root.val;
}
if(L < root.val) {
dfs(root.left, L, R);
}
if(root.val < R) {
dfs(root.right, L, R);
}
}