贪心算法

455 分发饼干

给一个孩子的饼干应当尽量小又能满足该孩子,这样大饼干就能拿来给满足度比较大的孩子。因为最小的孩子最容易得到满足,所以先满足最小的孩子。

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

435 无重叠区间

在每次选择中,区间的结尾最为重要,选择的区间结尾越小,留给后面的区间的空间越大,那么后面能够选择的区间个数也就越大。

按区间的结尾进行排序,每次选择结尾最小,并且和前一个区间不重叠的区间。

    public int eraseOverlapIntervals(int[][] intervals) {
        if(intervals==null || intervals.length==0 || intervals[0].length==0)
            return 0;
        Arrays.sort(intervals,Comparator.comparingInt(o1->o1[1]));
        int cnt=1;
        int end=intervals[0][1];
        for(int i=1;i<intervals.length;i++){
            if(intervals[i][0]>=end){
                cnt++;
                end=intervals[i][1];
            }
        }
        return intervals.length-cnt;
    }

Arrays.sort(intervals,Comparator.comparingInt(o1->o1[1]));也可写成

Arrays.sort(intervals, new Comparator<Interval>() {
    @Override
    public int compare(Interval o1, Interval o2) {
        return o1.end - o2.end;
    }
});

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

也是计算不重叠的区间个数,不过和 Non-overlapping Intervals 的区别在于,[1, 2] 和 [2, 3] 在本题中算是重叠区间。

    public int findMinArrowShots(int[][] points) {
        if(points==null || points.length==0)
            return 0;
        Arrays.sort(points,Comparator.comparingInt(o->o[1]));
        int count=1;
        int end=points[0][1];
        for(int i=1;i<points.length;i++){
            if(points[i][0]>end){
                count++;
                end=points[i][1];
            }
        }
        return count;
    }

406 根据身高重建队列

为了使插入操作不影响后续的操作,身高较高的学生应该先做插入操作,否则身高较小的学生原先正确插入的第 k 个位置可能会变成第 k+1 个位置。

    public int[][] reconstructQueue(int[][] people) {
        
        if(people==null || people.length==0)
            return new int[0][0];
        //按身高大小从大到小排序,若身高一样,则按第二个数从小到大排序
        Arrays.sort(people,(o1,o2)->(o1[0]==o2[0]?o1[1]-o2[1]:o2[0]-o1[0]));
        List<int[]> list=new ArrayList<>();
        for(int[] p:people){
            list.add(p[1],p);
        }
        return list.toArray(new int[list.size()][2]);
    }

763 划分字母区间

先遍历一次字符串,记录字符最后出现的位置。根据最后位置来判断该字符串区间最后的位置

    public List<Integer> partitionLabels(String S) {
        List<Integer> result=new ArrayList<>();
        if(S==null || S.length()==0)
            return result;
        int[] lastIndex=new int[26];
        for(int i=0;i<S.length();i++){
            lastIndex[S.charAt(i)-'a']=i;
        }
        int i=0;
        while(i<S.length()){
            int last=i;
            for(int j=i;j<S.length() && j<=last;j++){
                int tmp=lastIndex[S.charAt(j)-'a'];
                if(tmp>last)
                    last=tmp;
            }
            result.add(last-i+1);
            i=last+1;
        }
        return result;
    }

605 种花问题

    public boolean canPlaceFlowers(int[] flowerbed, int n) {
        int count=0;
        int pre,post;
        for(int i=0;i<flowerbed.length;i++){
            if(flowerbed[i]==0){
                pre=i==0?0:flowerbed[i-1];
                post=i==flowerbed.length-1?0:flowerbed[i+1];
                if(pre==0 && post==0){
                    count++;
                    flowerbed[i]=1;
                }
                if(count>=n){
                    break;
                }
            }
        }
        return count>=n;
    }

392 判断子序列

此题还可以利用指针

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

665 非递减数列

在出现 nums[i] < nums[i - 1] 时,需要考虑的是应该修改数组的哪个数,使得本次修改能使 i 之前的数组成为非递减数组,并且 不影响后续的操作 。优先考虑令 nums[i - 1] = nums[i],因为如果修改 nums[i] = nums[i - 1] 的话,那么 nums[i] 这个数会变大,就有可能比 nums[i + 1] 大,从而影响了后续操作。还有一个比较特别的情况就是 nums[i] < nums[i - 2],只修改 nums[i - 1] = nums[i] 不能使数组成为非递减数组,只能修改 nums[i] = nums[i - 1]。

    public boolean checkPossibility(int[] nums) {
        if(nums==null || nums.length==0)
            return false;
        int count = 0;
        for(int i=1;i<nums.length;i++){
            if(nums[i]<nums[i-1]){
                count++;
                if(count>=2){
                    return false;
                }
                if(i>=2 && nums[i-2]>nums[i]){
                    nums[i]=nums[i-1];
                }else{
                    nums[i-1]=nums[i];
                }
                
            }
        }
        return count<=1;
    }

122 买卖股票的最佳时机 II

    public int maxProfit(int[] prices) {
        if(prices==null || prices.length==0)
            return 0;
        int sum=0;
        for(int i=1;i<prices.length;i++){
            sum+=prices[i]>prices[i-1]?prices[i]-prices[i-1]:0;
        }
        return sum;
    }

53 最大子序和

    public int maxSubArray(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;
    }

121 买卖股票的最佳时机

只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为售出价格,查看当前收益是不是最大收益。

    public int maxProfit(int[] prices) {
        if(prices==null || prices.length==0)
            return 0;
        int min=prices[0];
        int max=0;
        for(int i=1;i<prices.length;i++){
            if(min>prices[i]){
                min=prices[i];
            }else{
                max=Math.max(max,prices[i]-min);
            }
        }
        return max;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值