LeetCode刷题总结:贪心算法 Java实现

定义

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。

455. Assign Cookies分配饼干 (Easy)

Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie.

Each child i has a greed factor g[i], which is the minimum size of a cookie that the child will be content with; and each cookie j has a size s[j]. If s[j] >= g[i], we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number.

有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃一个饼干,且只有饼干的大小不小于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩子可以吃饱。
输入两个数组,分别代表孩子的饥饿度和饼干的大小。输出最多有多少孩子可以吃饱的数量。

Example 1:

Input: g = [1,2,3], s = [1,1]
Output: 1
Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3.
And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content.
You need to output 1.

Example 2:

Input: g = [1,2], s = [1,2,3]
Output: 2
Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2.
You have 3 cookies and their sizes are big enough to gratify all of the children,
You need to output 2.

Constraints:

  • 1 <= g.length <= 3 * 104
  • 0 <= s.length <= 3 * 104
  • 1 <= g[i], s[j] <= 231 - 1

思路

这里使用贪心策略,不断将最小饥饿度的孩子分配最小且能吃饱的饼干。因为需要获得大小关系,所以使用数组的sort()方法,这样就可以的到最小饥饿度的孩子和最小的饼干。

代码

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g); 
        Arrays.sort(s);
        int g1=0, s1=0;
        while (g1 < g.length && s1 < s.length) {
            if (g[g1] <= s[s1]) ++g1;
            ++s1;
        }
        return g1;
    }
}

135 Candy 糖果(Hard)

There are n children standing in a line. Each child is assigned a rating value given in the integer array ratings.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
Return the minimum number of candies you need to have to distribute the candies to the children.

一群孩子站成一排,每一个孩子有自己的评分。现在需要给这些孩子发糖果,规则是如果一个孩子的评分比自己身旁的一个孩子要高,那么这个孩子就必须得到比身旁孩子更多的糖果;所有孩子至少要有一个糖果。求解最少需要多少个糖果。

输入是一个数组,表示孩子的评分。输出是最少糖果的数量。

Example 1:

Input: ratings = [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Example 2:

Input: ratings = [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.

Constraints:

  • n == ratings.length
  • 1 <= n <= 2 * 104
  • 0 <= ratings[i] <= 2 * 104

思路

题目需要求出最少分配所需的糖果数。运用贪心算法,只需要两次遍历即可,建立数组a,设初始值a[0]=1,先从左往右遍历,若右边大于左边,则右边的数为左边孩子糖果数加一,否则右边孩子糖果数为1。第二次从右往左遍历,若左边孩子评分比右边孩子高,且左边孩子糖果不大于右边孩子,则左边孩子糖果数变为右边孩子糖果数加一。贪心策略为每次遍历只考虑相邻一侧的大小关系

代码

class Solution {
    public int candy(int[] ratings) {
        int size = ratings.length;
        if (size < 2) {
            return size;
        }
        int[] a = new int[size];
        a[0] = 1;
        for (int i =1; i < size; ++i) {
            if (ratings[i] > ratings[i-1]) {
                a[i] = a[i-1] + 1;
            } else a[i] =1;
        }
        for (int i = size-1; i > 0; --i) {
            if (ratings[i] < ratings[i-1]) {
                a[i-1] = Math.max(a[i-1], a[i] +1);
            }           
        }
        int sum = 0;
        for( int num : a) {
            sum = sum + num;
        }
        return sum;
    }
}

435 Non-overlapping Intervals 无重叠区间 (Medium)

Given an array of intervals intervals where intervals[i] = [starti, endi], return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.

给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数。起止相连不算重叠。
输入是一个数组,数组由多个长度固定为 2 的数组组成,表示区间的开始和结尾。输出一个整数,表示需要移除的区间数量。

Example 1:

Input: intervals = [[1,2],[2,3],[3,4],[1,3]]
Output: 1
Explanation: [1,3] can be removed and the rest of the intervals are non-overlapping.

Example 2:

Input: intervals = [[1,2],[1,2],[1,2]]
Output: 2
Explanation: You need to remove two [1,2] to make the rest of the intervals non-overlapping.
Example 3:

Input: intervals = [[1,2],[2,3]]
Output: 0
Explanation: You don’t need to remove any of the intervals since they’re already non-overlapping.

Constraints:

  • 1 <= intervals.length <= 2 * 104
  • intervals[i].length == 2
  • -2 * 104 <= starti < endi <= 2 * 104

思路

解题思路为选择区间的结尾越小,留给其他区间的空间就越大。因此贪心策略为优先保留结尾小且与前一个区间不重叠的区间
首先将不同区间按照结尾的大小进行增序排序,然后每次选择结尾最小且与前一个区间不重叠的区间。
ps:intervals[0][1]代表第一个区间的结尾元素,而intervals[i][0]代表下一个区间的开始元素。

代码

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length == 0) {
            return 0;
        }
        int n =intervals.length;
        Arrays.sort(intervals, new Comparator<int[]>(){
            public int compare(int[] interval1, int[] interval2){
                return interval1[1] - interval2[1];
            }
        });
        int total = 0;
        int prev = intervals[0][1];
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] < prev){
                 ++total;
            } else {
                prev = intervals[i][1];
            }
        }
    return total;
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值