zoukankan      html  css  js  c++  java
  • 算法学习:二分法从入门到精通

    今天在力扣看到一道题,顺手写了下,用到了二分法和贪心算法,这里记录一下思路。

    二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:
    (1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
    (2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
    (3)如果某一步数组为空,则表示找不到目标元素。

    案例:

    题目:从一个排好序的数组中找到固定值的下标。

    代码:

    function binary_search(arr, key) {
        var low = 0,
            high = arr.length - 1;
    
        while (low <= high) {
            var mid = parseInt((high + low) / 2);
            if (key == arr[mid]) {
                return mid;
            } else if (key > arr[mid]) {
                low = mid + 1;
            } else if (key < arr[mid]) {
                high = mid - 1;
            } else {
                return -1;
            }
        }
    }

    从上方的代码中,大致了解了二分法是个什么东西,核心是减少循环次数,用最少的方法,返回准确的结果,节约内存,提高效率。

    下面是进阶题目:

    传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。

    传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

    返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。

    示例 1:

    输入:weights = [1,2,3,4,5,6,7,8,9,10], D = 5
    输出:15
    解释:
    船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示:
    第 1 天:1, 2, 3, 4, 5
    第 2 天:6, 7
    第 3 天:8
    第 4 天:9
    第 5 天:10
    
    请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。

    示例 2:

    输入:weights = [3,2,2,4,1,4], D = 3
    输出:6
    解释:
    船舶最低载重 6 就能够在 3 天内送达所有包裹,如下所示:
    第 1 天:3, 2
    第 2 天:2, 4
    第 3 天:1, 4

    示例 3:

    输入:weights = [1,2,3,1,1], D = 4
    输出:3
    解释:
    第 1 天:1
    第 2 天:2
    第 3 天:3
    第 4 天:1, 1

    下面是我的答案:

    var shipWithinDays = function(weights, D) {
          let l = Math.max(...weights),r = weights.reduce((n,m) => n + m);
        while(l < r){
            let r1 = (r - l) % 2 == 1 ? (r - l - 1) / 2: (r - l) / 2;
            let mid = l + r1;
            if(getWeight(weights,mid) <= D){
                r = mid;
            }else{
                l = mid + 1;
            }
        }
    
        function getWeight(arr,k){
            let sum = 1;
            let s = 0;
            for(let i = 0; i < arr.length; i++){
                if(s + arr[i] <= k){
                    s += arr[i];
                }else{
                    s = arr[i];
                    sum++;
                }
            }
            return sum;
        }
        return l;
    };

    思路是以数组里的最大值为初始值,总和值为结尾值,用二分法来查询,减少次数,有兴趣可以看下代码研究下。

  • 相关阅读:
    Microsoft Enterprise Library 5.0 系列(二) Cryptography Application Block (初级)
    Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block
    Microsoft Enterprise Library 5.0 系列(八) Unity Dependency Injection and Interception
    Microsoft Enterprise Library 5.0 系列(九) Policy Injection Application Block
    Microsoft Enterprise Library 5.0 系列(三) Validation Application Block (高级)
    软件研发打油诗祝大家节日快乐
    从挖井的故事中想到开发管理中最容易忽视的几个简单道理
    ITIL管理思想的执行工具发布
    管理类软件设计“渔”之演化
    20070926日下午工作流与ITILQQ群 事件管理 讨论聊天记录
  • 原文地址:https://www.cnblogs.com/smileZAZ/p/14704291.html
Copyright © 2011-2022 走看看