leetcode贪心专题

贪心

455. Assign Cookies (Easy)

分配饼干:每个孩子都有一个满足度 grid,每个饼干都有一个大小 size,只有饼干的大小大于等于一个孩子的满足度,该孩子才会获得满足。求解最多可以获得满足的孩子数量。

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

435. Non-overlapping Intervals (Medium)

计算让一组区间不重叠所需要移除的区间个数。

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

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length == 0)
            return 0;
        Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1] - o2[1];
            }
        });
        int cnt = 1;
        int end = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] < end)
                continue;
            end = intervals[i][1];
            cnt++;
        }
        return intervals.length - cnt;
    }
}

尤其记一下这个comparator的写法

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

452. Minimum Number of Arrows to Burst Balloons (Medium)

和上一题没什么区别

class Solution {
    public int findMinArrowShots(int[][] points) {
        int length = points.length;
        if (length == 0)
            return 0;
        Arrays.sort(points, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1] - o2[1];
            }
        });
        int cnt = 1;
        int end = points[0][1];
        for (int i = 1; i < length; i++) {
            if (points[i][0] <= end)
                continue;
            end = points[i][1];
            cnt++;
        }
        return cnt;
    }
}

406. Queue Reconstruction by Height(Medium)

官方题解讲的超级好

因为个子矮的人相对于个子高的人是 “看不见” 的,所以可以先安排个子高的人。

所以首先身高降序排
相同身高的人再按照k升序排

在排序好的这些人中,从前往后(也就是从高到低)往另一个数组里加,把人放在自己下标所在的位置即可(因为比自己矮的人看不见,比自己高的人已经放好了,和自己一样高的人下标比自己小也已经放好了)

(感觉有点只可意会不可言传怎么回事)

class Solution {
    public int[][] reconstructQueue(int[][] people) {
      Arrays.sort(people, new Comparator<int[]>() {
        @Override
        public int compare(int[] o1, int[] o2) {
          return o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0];
        }
      });
      List<int[]> output = new LinkedList<>();
      for(int[] p : people){
        output.add(p[1], p);
      }
      int n = people.length;
      return output.toArray(new int[n][2]);
    }
}

121.Best Time to Buy and Sell Stock (Easy)

买卖股票最大的收益

有n天,有每一天股票的价格,问怎么买能使得最后的利润最大

用一个min来记录当前出现的最低价格,然后今天的价格-min就是今天买入的利润,选出最大的利润即可

class Solution {
    public int maxProfit(int[] prices) {
        int length = prices.length;
        if (length == 0)
            return 0;
        int min = Integer.MAX_VALUE;
        int ans = -1;
        for (int i : prices) {
            min = Math.min(min, i);
            ans = Math.max(ans, i - min);
        }
        return ans;
    }
}

122. Best Time to Buy and Sell Stock II (Easy)

在上一题的基础上,可以进行多笔交易

至今还是不明白为什么这样可以得到最优解👇

class Solution {
    public int maxProfit(int[] prices) {
        int length = prices.length;
        if (length == 0)
            return 0;
        int ans = 0;
        for (int i = 1; i < length; i++) {
            if (prices[i] > prices[i - 1])
                ans += prices[i] - prices[i - 1];
        }
        return ans;
    }
}

605. Can Place Flowers (Easy)

flowerbed 数组中 1 表示已经种下了花朵。花朵之间至少需要一个单位的间隔,求解是否能种下 n 朵花。

从前往后扫即可,注意各种边界情况

class Solution {
    public boolean canPlaceFlowers(int[] flowerbed, int n) {
        int length = flowerbed.length;
        int cnt = 0;
        if (length == 0)
            return false;
        for (int i = 0; i < length; i++) {
            if (flowerbed[i] == 0) {
                if (length == 1 && flowerbed[i] == 0)
                    cnt++;
                else if (i == 0 && i + 1 < length && flowerbed[i + 1] == 0)
                    cnt++;
                else if (i == length - 1 && i - 1 > 0 && flowerbed[i - 1] == 0)
                    cnt++;
                else if (i - 1 > 0 && flowerbed[i - 1] == 0 && i + 1 < length && flowerbed[i + 1] == 0) {
                    flowerbed[i] = 1;
                    cnt++;
                }
            }
        }
        return cnt >= n;
    }
}

392. Is Subsequence (Medium)

判断是不是子序列

用 Java自带的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;
}

665.Non-decreasing Array (Easy)

修改一个数使数组成为非递减数

判断nums[i]和nums[i-1]的大小关系

  1. nums[i] >= nums[i-1] : continue

  2. nums[i] < nums[i-1]

    此时是需要修改一个值使得nums[i] >= nums[i-1]

    问题是令nums[i] = nums[i-1]. 还是 令 nums[i-1] = nums[i]

    两种情况:

    • nums[i] >= nums[i-2],如下图所示:

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SBHVkk5H-1580452605907)(/Users/dylan/Library/Application Support/typora-user-images/image-20200131134903167.png)]

      此时修改nums[i-1] = nums[i],如下图
      这样不会对后续的数字有影响,如果把nums[i]改大了,有可能比后面的数还要大,所以修改nums[i-1]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pG4qv86t-1580452605909)(/Users/dylan/Library/Application Support/typora-user-images/image-20200131135007603.png)]

    • 如果nums[i] < nums[i-2],如下图:

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3EyAKldV-1580452605910)(/Users/dylan/Library/Application Support/typora-user-images/image-20200131135238680.png)]

      就修改nums[i] = nums[i-1]:

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avCsPISF-1580452605911)(/Users/dylan/Library/Application Support/typora-user-images/image-20200131135459434.png)]

代码:

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

53. Maximum Subarray (Easy)

子数组最大的和

我用dp做的没用贪心(小声

class Solution {
    public int maxSubArray(int[] nums) {
        int length = nums.length;
        if (length == 0)
            return 0;
        int[] dp = new int[length];
        dp[0] = nums[0];
        int max = nums[0];
        for (int i = 1; i < length; i++) {
            dp[i] = dp[i - 1] > 0 ? dp[i - 1] + nums[i] : nums[i];
            max = Math.max(max, dp[i]);
        }
        return max;
    }
}

763. Partition Labels (Medium)

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。

首先记录每一个字母出现的最后位置

d e g d e h i g j

字母degdehigj
下标012345678
字母degijh
最后出现的位置347685

遍历的时候不断更新当前段字母出现的最后位置,这个最后的位置就是这个段的结束位置

遍历到的字母下标最后出现的位置当前段的下标下标==当前段的下标?
未开始--0
d033
e144
g277
d337
e447
h557
i667
g777嗯!

(差不多就是这么个意思,列表好麻烦就酱了)

代码:

class Solution {
    public List<Integer> partitionLabels(String string) {
        int length = string.length();
        List<Integer> list = new ArrayList<>();
        if (length == 0)
            return list;
        int[] right = new int[26];
        for (int i = 0; i < length; i++) {
            right[string.charAt(i) - 'a'] = i;
        }
        int max = 0;
        int lastIndex = 0;
        for (int i = 0; i < length; i++) {
            max = Math.max(max, right[string.charAt(i) - 'a']);
            if (i == max) {
                list.add(i - lastIndex + 1);
                lastIndex = i + 1;
            }
        }
        return list;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值