算法沉淀——贪心算法一(leetcode真题剖析)

小明 2025-04-28 04:54:34 6

算法沉淀——贪心算法一

  • 01.柠檬水找零
  • 02.将数组和减半的最少操作次数
  • 03.最大数
  • 04.���动序列

    贪心算法(Greedy Algorithm)是一种基于贪心策略的优化算法,它通常用于求解最优化问题,每一步都选择当前状态下的最优解,以期望通过局部最优的选择最终达到全局最优。贪心算法的思想是在每一步都做出在当前状态下局部最优的选择,而不考虑未来可能造成的影响。

    在应用贪心算法时,通常需要满足两个基本要素:

    1. 最优子结构性质(Optimal Substructure): 问题的最优解包含了其子问题的最优解。这意味着通过解决子问题可以得到原问题的最优解。
    2. 贪心选择性质(Greedy-Choice Property): 在做每一步的选择时,选择当前状态下的最优解,即局部最优解。这样希望通过局部最优选择达到全局最优。

    贪心算法适用于一些特定类型的问题,但并不适用于所有问题。它通常比动态规划算法更加高效,因为它不需要考虑所有可能的解,只需选择当前状态下的最优解。然而,贪心算法的局限性在于可能会错过全局最优解,因为它没有考虑未来的影响。

    经典应用贪心算法的问题包括:

    • 活动选择问题(Activity Selection Problem): 选择一组互不相交的活动,使得参与的活动数最大。
    • 霍夫曼编码(Huffman Coding): 用变长编码表示不同字符,使得编码长度的加权和最小。
    • 最小生成树问题(Minimum Spanning Tree Problem): 在一个连通图中找到一棵包含所有顶点的树,使得树上边的权值之和最小。
    • 单源最短路径问题的Dijkstra算法: 在一个带权图中,从一个顶点出发,找到到达其他顶点的最短路径。

      需要注意的是,贪心算法并不总是能够找到问题的最优解,因此在应用时需要仔细分析问题的性质,确定贪心选择是否能够保证得到全局最优解。

      01.柠檬水找零

      题目链接:https://leetcode.cn/problems/lemonade-change/

      在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

      每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

      注意,一开始你手头没有任何零钱。

      给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

      示例 1:

      输入:bills = [5,5,5,10,20]
      输出:true
      解释:
      前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
      第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
      第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
      由于所有客户都得到了正确的找零,所以我们输出 true。
      

      示例 2:

      输入:bills = [5,5,10,10,20]
      输出:false
      解释:
      前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
      对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
      对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
      由于不是每位顾客都得到了正确的找零,所以答案是 false。
      

      提示:

      • 1 public: bool lemonadeChange(vector int five = 0, ten = 0; for(int& x:bills){ if(x==5) five++; else if(x==10){ if(five==0) return false; five--;ten++; } else{ if(ten&&five){ ten--;five--; } else if(five=3) five-=3; else return false; } } return true; } }; h202.将数组和减半的最少操作次数/h2 p题目链接:https://leetcode.cn/problems/minimum-operations-to-halve-array-sum//p p给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作)/p p请你返回将 nums 数组和 至少 减少一半的 最少 操作数。/p p示例 1:/p pre class="brush:python;toolbar:false"输入:nums = [5,19,8,1] 输出:3 解释:初始 nums 的和为 5 + 19 + 8 + 1 = 33 。 以下是将数组和减少至少一半的一种方法: 选择数字 19 并减小为 9.5 。 选择数字 9.5 并减小为 4.75 。 选择数字 8 并减小为 4 。 最终数组为 [5, 4.75, 4, 1] ,和为 5 + 4.75 + 4 + 1 = 14.75 。 nums 的和减小了 33 - 14.75 = 18.25 ,减小的部分超过了初始数组和的一半,18.25 >= 33/2 = 16.5 。 我们需要 3 个操作实现题目要求,所以返回 3 。 可以证明,无法通过少于 3 个操作使数组和减少至少一半。

        示例 2:

        输入:nums = [3,8,20]
        输出:3
        解释:初始 nums 的和为 3 + 8 + 20 = 31 。
        以下是将数组和减少至少一半的一种方法:
        选择数字 20 并减小为 10 。
        选择数字 10 并减小为 5 。
        选择数字 3 并减小为 1.5 。
        最终数组为 [1.5, 8, 5] ,和为 1.5 + 8 + 5 = 14.5 。
        nums 的和减小了 31 - 14.5 = 16.5 ,减小的部分超过了初始数组和的一半, 16.5 >= 31/2 = 15.5 。
        我们需要 3 个操作实现题目要求,所以返回 3 。
        可以证明,无法通过少于 3 个操作使数组和减少至少一半。
        

        提示:

        • 1 public: int halveArray(vector priority_queue heap.push(x); sum+=x; } sum/=2.0; int count=0; while(sum0){ double tmp=heap.top()/2.0; heap.pop(); sum-=tmp; count++; heap.push(tmp); } return count; } }; public: string largestNumber(vector vectorreturn s1+s2s2+s1;}); string ret; for(string& s:strs) ret+=s; if(ret[0]=='0') return "0"; return ret; } }; public: int wiggleMaxLength(vector int n=nums.size(); if(n int right = nums[i+1]-nums[i]; if(right==0) continue; if(right*left
The End
微信