贪心算法题型总结

发布于:2023-01-09 ⋅ 阅读:(481) ⋅ 点赞:(0)

🍋什么是贪心算法?

贪心算法:是一种思想,解答要根据具体题目来编写代码,它让每一步都是局部最优的方案。

🍋1. 分配饼干

题目描述链接

https://leetcode.cn/problems/assign-cookies/

题目特点

寻找最优解,一维数组。

代码实现

贪心大致思路:先边界判断,直接排序,后找到需要的情况返回。

public int findContentChildren(int[] g, int[] s) {
    if (g==null || s==null){
        return 0;
    }
    Arrays.sort(g);
    Arrays.sort(s);
    int i=0,j=0;
    while(i<g.length&&j<s.length){
        if (g[i]<=s[j]){
            j++;
        }
        i++;
    }
    return j;
}

时间复杂度和空间复杂度

时间复杂度:O(NlogN);

空间复杂度:O(N)。

🍋2. 不重叠的区间个数

题目描述链接

https://leetcode.cn/problems/non-overlapping-intervals/

题目特点

寻找最优解,一维数组。

代码实现

贪心大致思路:先边界判断,直接排序,后找到需要的情况返回。

public int eraseOverlapIntervals(int[][] intervals) {
    //边界判断
    if (intervals==null){
        return 0;
    }
    //排序
    Arrays.sort(intervals, new Comparator<int[]>() {
        @Override
        public int compare(int[] o1, int[] o2) {
            return (o1[1]<o2[1])?-1:(o1[1]==o2[1]?0:1);
        }
    });
    //找到符合条件的情况
    int ans=0;
    int right=intervals[0][1];
    for (int i = 0; i < intervals.length; i++) {
        if (intervals[i][0]>=right){
            ans++;
            right=intervals[i][1];
        }
    }
    return intervals.length-ans;
}

时间复杂度和空间复杂度

时间复杂度:O(NlogN);

空间复杂度:O(N)。

🍋3. 投飞镖刺破气球

题目描述链接

https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/

题目特点

寻找最优解,一维数组。

代码实现

贪心大致思路:先边界判断,直接排序,后找到需要的情况返回。

public int findMinArrowShots(int[][] points) {
    //先判断边界条件
    if (points==null){
        return 0;
    }
    //排序
    Arrays.sort(points, new Comparator<int[]>() {
        @Override
        public int compare(int[] o1, int[] o2) {
            return o1[1]<o2[1]?-1:(o1[1]==o2[1]?0:1);
        }
    });
    //找到符合条件的情况
    int ans=1;
    int index=points[0][1];
    for (int i = 0; i < points.length; i++) {
        if(index<points[i][0]){
            ans++;
            index=points[i][1];
        }
    }
    return ans;
}

时间复杂度和空间复杂度

时间复杂度:O(NlogN);

空间复杂度:O(N)。

🍋4. 根据身高和序号重组队列

题目描述链接

https://leetcode.cn/problems/queue-reconstruction-by-height/

题目特点

寻找正确队列的组合。

代码实现

贪心大致思路:先边界判断,直接排序,后找到需要的情况返回。

public static int[][] reconstructQueue1(int[][] people) {
    if (people==null){
        return people;
    }
    //根据身高降序排列,K值升值排列
    Arrays.sort(people, (a, b) ->  a[0] == b[0]? a[1] - b[1] : b[0] - a[0]);
    List<int[]> list = new ArrayList<>();
    //遍历people,添加进list
    for(int[] secondArray : people){
        list.add(secondArray[1], secondArray);
    }
    //插入完成, 输入到int[][]输出
    //将list变成二维数组
    return list.toArray(new int[list.size()][]);
}

时间复杂度和空间复杂度

时间复杂度:O(NlogN);

空间复杂度:O(N)。

🍋5. 买卖股票最大的收益

题目描述链接

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/

题目特点

不考虑前一天的情况,买入最低,卖出最高,与天数有关,不需要排序。

代码实现

贪心大致思路:先判断边界条件,不需要排序,因为需要用到索引,处理遍历一维数组就搞定了。

public static int maxProfit(int[] prices) {
    //先判断边界条件
    if (prices.length==0||prices.length==1){
        return 0;
    }
    //排序,不需要
    //处理
    int minBuy=prices[0];
    int max=0;
    for (int i = 1; i < prices.length; i++) {
        if (minBuy>prices[i]){
            minBuy=prices[i];
        }else{
            max=Math.max(max,prices[i]-minBuy);
        }
    }
    return max;
}

时间复杂度和空间复杂度

时间复杂度:O(N);

空间复杂度:O(1)。

🍋6. 买卖股票的最大收益 II

题目描述链接

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/

题目特点

与第五题相比,可以随买随卖,可以购买n次。

代码实现

贪心大致思路:先判断边界条件,不需要排序,因为需要用到索引,处理遍历一维数组就搞定了。

public static int maxProfit(int[] prices) {
    //先判空
    if (prices.length == 0 || prices.length == 1) {
        return 0;
    }
    //与索引值绑定很深,不需要排序
    //处理
    int minBuy = prices[0];
    int max = 0;
    int sum = 0;
    for (int i = 1; i < prices.length; i++) {
        if (minBuy > prices[i] || prices[i - 1] > prices[i]) {
            minBuy = prices[i];
            sum += max;
            max = 0;
        } else {
            max = Math.max(max, prices[i] - minBuy);
        }
    }
    sum += max;
    return sum;
}

改进版本:

public static int maxProfit1(int[] prices) {
    int max=0;
    for (int i = 1; i < prices.length; i++) {
        if (prices[i]>prices[i-1]){
            max += prices[i]-prices[i-1];
        }
    }
    return max;
}

时间复杂度和空间复杂度

时间复杂度:O(N)VSO(N);

空间复杂度:O(1)VS(1)。

🍋7. 种植花朵

题目描述链接

https://leetcode.cn/problems/can-place-flowers/

题目特点

所走的每一步都要满足局部最优。

代码实现

贪心算法:

public static boolean canPlaceFlowers2(int[] flowerbed, int n) {
    int len=flowerbed.length;
    int cnt=0;
    for (int i = 0; i < len; i++) {
        if (flowerbed[i]==1){
            continue;
        }
        int pre= i==0?0:flowerbed[i-1];
        int next= i==len-1?0:flowerbed[i+1];
        if (pre==0&&next==0){
            cnt++;
            flowerbed[i]=1;
        }
    }
    return cnt>=n;
}

时间复杂度和空间复杂度

时间复杂度:O(N),

空间复杂度:O(1)。

🍋8. 判断是否为子序列

题目描述链接

https://leetcode.cn/problems/is-subsequence/

题目特点

一维数组,找对应的字串。

代码实现

暴力破解:

public boolean isSubsequence(String s, String t) {
    int count=0;
    int index=0;
    for (int i = 0; i < s.length(); i++) {
        for (int j = index; j < t.length(); j++) {
            if (s.charAt(i)==t.charAt(j)){
                count++;
                index=j+1;
                break;
            }
        }
    }
    return count==s.length();
}

巧用字符串的indexof方法:

public boolean isSubsequence(String s, String t) {
    int index=-1;
    for (char c:s.toCharArray()) {
        index=t.indexOf(c,index+1);
        if (index==-1){
            return false;
        }
    }
    return true;
}

时间复杂度和空间复杂度

时间复杂度:O(N2)VSO(N2);

空间复杂度:O(1)VSO(1)。

🍋9. 修改一个数成为非递减数组

题目描述链接

https://leetcode.cn/problems/non-decreasing-array/

题目特点

一维数组,最多修改一次就符合条件意思。

代码实现

贪心:

public boolean checkPossibility(int[] nums) {
    int cnt=0;
    for (int i = 1; i < nums.length; i++) {
        if (nums[i]>=nums[i-1]){
            continue;
        }
        cnt++;
        if (i-2>=0&&nums[i-2]>nums[i]){
            nums[i]=nums[i-1];// 3 ,4 ,1
        }else{
            nums[i-1]=nums[i];// 4, 2, 3
        }
    }
    return cnt<=1 ;
}

时间复杂度和空间复杂度

时间复杂度:O(N);

空间复杂度:O(1)。

🍋10. 子数组最大的和

题目描述链接

https://leetcode.cn/problems/maximum-subarray/

题目特点

一维数组,往下走的每一步都需要最优的。

代码实现

贪心:

public static int maxSubArray1(int[] nums) {
    //边界判断
    if (nums==null||nums.length==0){
        return 0;
    }
    int preSum = nums[0];
    int maxSum = preSum;
    for (int i = 1; i < nums.length; i++) {
        preSum = preSum > 0 ? preSum + nums[i] : nums[i];
        maxSum = Math.max(maxSum, preSum);
    }
    return maxSum;
}

时间复杂度和空间复杂度

时间复杂度:O(N);

空间复杂度:O(1)。

🍋11. 分隔字符串使同种字符出现在一起

题目描述链接

https://leetcode.cn/problems/partition-labels/

题目特点

一维数组,要求尽可能多的问题。

代码实现

贪心:走的每一步都是最优的,根据题目意思编码代码。

public List<Integer> partitionLabels(String s) {
    int[] last = new int[26];
    int length = s.length();
    for (int i = 0; i < length; i++) {
        last[s.charAt(i) - 'a'] = i;
    }
    List<Integer> partition = new ArrayList<Integer>();
    int start = 0, end = 0;
    for (int i = 0; i < length; i++) {
        end = Math.max(end, last[s.charAt(i) - 'a']);
        if (i == end) {
            partition.add(end - start + 1);
            start = end + 1;
        }
    }
    return partition;
}

时间复杂度和空间复杂度

时间复杂度:O(N^2);

空间复杂度:O(1-N)。

🍋题型总结

使用条件:

  1. 出现最大、最小、尽可能多、尽可能少等字眼,可能要用到贪心算法;
  2. 大部分的贪心算法题目,虽然是一维数组,但是数组的下标有一定的用处;
  3. 全局最优解可以通过多个局部最优解得到(最重要的一点)。

网站公告

今日签到

点亮在社区的每一天
去签到

热门文章