(Typescript)[leetcode]1011. Capacity To Ship Packages Within D Days

(Typescript)[leetcode]1011. Capacity To Ship Packages Within D Days

思想:二分法模板,抽象出单调函数,寻最值

function binarySearch(nums: number[], target: number) {
    let left = 0, right = nums.length - 1;

    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2)
        if (nums[mid] == target) {
            return mid
        } else if (nums[mid] < target) {
            left = mid + 1
        } else if (nums[mid] > target) {
            right = mid - 1
        }
    }
    return -1
}

function leftBound(nums: number[], target: number) {
    if (nums.length == 0) return -1
    let left = 0, right = nums.length; // 注意

    while (left < right) {  // 注意
        let mid = left + Math.floor((right - left) / 2)
        if (nums[mid] == target) {
            right = mid
        } else if (nums[mid] < target) {
            left = mid + 1
        } else if (nums[mid] > target) {
            right = mid   // 注意
        }
    }
    return -1
}


function leftBound01(nums: number[], target: number) {
    if (nums.length == 0) return -1
    let left = 0, right = nums.length - 1

    // 搜索区间为[left, right]
    while (left <= right) {  // 注意
        let mid = left + Math.floor((right - left) / 2)
        if (nums[mid] < target) {
            // 搜索区间变为[mid +1 , right]
            left = mid + 1
        } else if (nums[mid] > target) {
            // 搜索区间变为[left , mid -1]
            right = mid - 1
        } else if (nums[mid] == target) {
            // 收缩右侧边界
            right = mid - 1
        }
    }

    // 检查出界情况
    if (left >= nums.length || nums[left] != target) {
        return -1
    }
    return left
}


function rightBound01(nums: number[], target: number) {
    if (nums.length == 0) return -1
    let left = 0, right = nums.length


    while (left < right) {
        let mid = left + Math.floor((right - left) / 2)
        if (nums[mid] == target) {
            left = mid + 1    // 注意
        } else if (nums[mid] < target) {
            left = mid + 1
        } else if (nums[mid] > target) {
            right = mid
        }
    }


    return right - 1 // 注意
}



function rightBound02(nums: number[], target: number) {
    if (nums.length == 0) return -1
    let left = 0, right = nums.length - 1

    // 搜索区间为[left, right]
    while (left <= right) {  // 注意
        let mid = left + Math.floor((right - left) / 2)
        if (nums[mid] < target) {
            // 搜索区间变为[mid +1 , right]
            left = mid + 1
        } else if (nums[mid] > target) {
            // 搜索区间变为[left , mid -1]
            right = mid - 1
        } else if (nums[mid] == target) {
            // 收缩左侧边界
            left = mid + 1
        }
    }

    // 检查出界情况 检查right越界的情况
    if (right < 0 || nums[right] != target) {
        return -1
    }
    return right
}




// 函数f是关于自变量x的单调函数
function f(x) {
    // 
    return x
}

// 主函数,在f(x) == target 的约束下,求x的最小值
function solution(nums: number[], target: number) {
    if (nums.length == 0) return -1

    // 问自己:自变量x的最小值是多少?
    let left = 0

    // 问自己 自变量x的最大值是多少?
    let right = nums.length + 1

    while (left < right) {
        let mid = left + Math.floor((right - left) / 2)
        if (f(mid) == target) {
            // 问自己: 题目是求左边界还是右边界?
            // ...
        } else if (f(mid) < target) {
            // 问自己:怎么让f(x)更大一点?
            // ...
        } else if (f(mid) > target) {
            // 问自己:怎么让f(x)更小一点?
            // ...
        }
    }

    return left
}

solution:

// 运输能力为x时,在f(x)天能将货物weights运输完
function f(weights: number[], x: number) {
    let days = 0

    for (let i = 0; i < weights.length;) {
        // 尽可能多装货物
        let cap = x
        while (i < weights.length) {
            if (cap < weights[i]) {
                break
            } else {
                cap -= weights[i]
            }
            i++
        }
        days++
    }

    return days
}

// 主函数,在f(x) == target 的约束下,求x的最小值 f(x)单调递减
function shipWithinDays(weights: number[], days: number): number {
    let left = Math.max(...weights);
    let right = weights.reduce((sum, curr) => {
        return sum + curr
    }, 1)

    while (left < right) {
        let mid = left + Math.floor((right - left) / 2)
        let tmp = f(weights, mid)

        if (tmp == days) {
            // 求左边界, 收缩右侧边界
            right = mid
        } else if (tmp < days) {
            // 怎么让f(x)更大一点? x变小
            right = mid
        } else if (tmp > days) {
            // 怎么让f(x)更小一点?x变大
            left = mid + 1
        }
    }

    return left
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值