贪心 - wenzhoullq/leetcode GitHub Wiki

思想

局部最优解满足全局最优解,局部最优解没有后置性,关键字最少/多/长/短

模拟贪心

模拟取最值

题目

1733. 需要教语言的最少人数

D. Cloud of Hashtags-2023.1.13

最值选择贪心

维护一个最小值nums[],当前值与nums[i+1]进行比较

题目

915. 分割数组

2434. 使用机器人打印字典序最小的字符串

反悔贪心

顺序访问,如果碰到不够的就加,或则将前面的去掉(用堆维护)

题目

802. 找到最终的安全状态

2383. 赢得比赛需要的最少训练时长

排序贪心

排序的方式需要直觉

题目

1665. 完成所有任务的最少初始能量

线性贪心

题目

754. 到达终点数字(一直加,加到和目标值差为偶数的时候返回,负数取绝对值

6152. 赢得比赛需要的最少训练时长 正常模拟,遇到不够的就补

1793. 好子数组的最大分数

2522. 将字符串分割成值不超过 K 的子字符串

区间贪心系列

区间最少数量覆盖

用优先队列,对left进行排序,然后对最大值维护

 Queue<int[]> q = new PriorityQueue<>((a,b)->a[0]-b[0]);
        int len = ranges.length;
        for(int i = 0; i < len ; i++ ){
            q.add(new int[]{});   
        }
        int ans = 0, max = 0 ;
        while(max<n){
           if(q.isEmpty()||q.peek()[0]>max) return -1;
           int right = max;
           while(!q.isEmpty()&&q.peek()[0] <= max)  right = Math.max(right,q.poll()[1]);
           if(right> max){
                ans++;
                max = right;
            }
        }
        return ans;

题目

45. 跳跃游戏 II

1326. 灌溉花园的最少水龙头数目

区间重叠贪心

先排序,再使用贪心

模板

      Arrays.sort(points,(a,b)->Integer.compare(a[0],b[0]));
        int ans=,right=points[0][1];
        for(int i=1;i<points.length;i++){
            if(right>=points[i][0]){
                right=Math.(right,points[i][1]);//right处理
                continue;
            }
            right=points[i][1];
        }
        return ans;

题目

56. 合并区间

435. 无重叠区间

452. 用最少数量的箭引爆气球

1546. 和为目标值且不重叠的非空子数组的最大数目

块排序

模板

对于一般的块排序,我们通常会先进行快排,然后在正确的结果上进行对比,来确定相应的答案,模板如下。

        int[] temp=(int[])arr.clone();
        int max=arr[0],ans=0;
        Arrays.sort(arr);
        for(int i=0;i<arr.length;i++){
            max=Math.max(max,temp[i]);
            if(max==arr[i]) ans++;
        }
        return ans;

如果会出现重复数字怎么办?把最大值改为区间和 然后接着深挖

   int max=nums[0],min=nums[length-1];//max是用来确定排序的尾端的,即end;min是用来确定排序的首端的,即start
   for(int i=0;i<nums.length;i++){
       if(max>nums[i])//说明此处排序结尾仍然是混乱的,当出现max>nums[i],无论是nums有无排序过,只要出现,存在一个数x,[end-x,end]是混乱的
       if(min<nums[i])//说明此处排序开头仍然是混乱的,当出现min<nums[i],无论是nums有无排序过,只要出现,存在一个数x,[start,start+x]是混乱的
   }
   

题目

581. 最短无序连续子数组

768. 最多能完成排序的块 II

769. 最多能完成排序的块

区间翻转贪心

  while(str!=target){
     1.找到不满足的且最大的位置
     2.该位置到末尾翻转
     3.ans++;
}
return ans;

题目

969. 煎饼排序

995. K 连续位的最小翻转次数 区间同一个数字的变化,还得用差分的思想

1529. 最少的后缀翻转次数 这题比较特殊,用区间翻转的思路可以,但是因为n太大了,会超时

2375. 根据模式串构造最小数字 因为要求字典序,因此先升序排序,然后对需要降序的部分进行反转

区间合并/组成贪心

题目

330. 按要求补齐数组

几个数字构成

相邻贪心

分析

数字之间存在关系,然后HashMap+贪心的思想去做

模板

        Arrays.sort(nums);
        HashMap<Integer,Integer> m=new HashMap<>();
        List<Integer> list=new LinkedList<>();
        for(int temp:nums){
            if(!m.containsKey(temp)) list.add(temp); 
            m.put(temp,m.getOrDefault(temp,0)+1);
        } 
        for(int temp:list){
            int num=m.get(temp);
            if(num<0) return false;
            if(num==0) continue;
            //贪心处理
        }

题目

954. 二倍数对数组

1296. 划分数组为连续数字的集合

消耗型贪心

消耗型贪心分两种,一种是减去具体的数,一种是除一个值,如果是除一个值的话,那么往往都伴随着+1/-1将其变为整除;无论是减法型贪心还是整除型贪心,他们都希望用最大的消耗(被减数最大,被除数最大)来先消耗,不足的再用别的来消耗

模板

  • 整除型消耗 模板有些粗糙,但是大概就是这个意思,即通过+1/-1的操作让n变得能被 2,3整除(2,3是题目给的),因为+1/-1操作远不如整除操作,当被1和2处理的时候,时间复杂度较低,而当出现可以被多个数,如2,3整除,会出现重复计算,因此用记忆化dfs可以降低重复计算的量
   main(int n,int target){
    if() return ;//如果到了边界,return相应的值
    return main(n%x+main(n/x))+1+n%x;//值得注意的是这里有个+1,即本次整除操作+1,而n%x则是+1操作
   }
  • 减法型消耗
     int mod=n%x;
      if(mod==0) ans+=n/x;
      else ans+=n/x+xx;

题目

991. 坏了的计算器 (正向情况太多,反向思考

1553. 吃掉 N 个橘子的最少天数 存在大量的重复计算,不如记忆化dfs

2244. 完成所有任务需要的最少轮数

回文贪心

模板

题目

1147. 段式回文

优先队列贪心

优先队列的本质是贪心

题目

23. 合并K个升序链表

407. 接雨水 II

  • 区间内最大差值的最小值

多指针+优先队列 每次取最小值

632. 最小区间 取优先队列的最后一个值有技巧,就是通过比较

1675. 数组的最小偏移量

  • 拼接字符串

一般来说,给予几个字符a,b,c和他的数量,都是可以用优先队列来做的,但是时间复杂度相对较高

984. 不含 AAA 或 BBB 的字符串

1405. 最长快乐字符串

1753. 移除石子的最大得分

  • 其他

1546. 和为目标值且不重叠的非空子数组的最大数目

暴力贪心

当数据较小的时候,考虑暴力的方式进行贪心,如果变量是一个则双重for循环进行暴力贪心,如果变量多个则用回溯进行贪心

题目

1024. 视频拼接

2305. 公平分发饼干

正反贪心

通过左边一次贪心和右边一次贪心得到,一般是跟相邻的比较或则同等位置的比较

题目

135. 分发糖果

838. 推多米诺 同2211

1671. 得到山形数组的最少删除次数 左右贪心+最长上升子序列

2211. 统计道路上的碰撞次数

2337. 移动片段得到字符串

6190. 找到所有好下标

B. Bear and Blocks

D2. Remove the Substring (hard version) 建立一个最早出现匹配和最晚出现匹配数组

匹配贪心

存在着多少个与它相同

主要是建立映射,与它不同的还有多少,累计的是否超过了它

题目

781. 森林中的兔子

Farewell Party

排序贪心

有点桶的思想

题目

A. Sorting Railway Cars

C. Maximum Median - 2023.4.10-灵茶 值得注意的是,k不能先减,因为arr[i] 和 arr[i-1]可能相差特别大,但是k均匀分布到前面还是可能的

拆分贪心

题目

6144. 将数组排序的最少替换次数 从右往左拆,拆的值取平均值

累计贪心

当全部完成一轮后+1

题目

2350. 不可能得到的最短骰子序列

有点像优先队列的贪心

题目

1953. 你可以工作的最大周数

俩俩抵消

俩俩抵消都是最大的两个抵消的

2856. 删除数对后的最小数组长度

⚠️ **GitHub.com Fallback** ⚠️