当前位置:   article > 正文

LeetCode —— 贪心算法_leetcode贪心算法

leetcode贪心算法

持续更新中........................

455. 分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

示例:输入: g = [1,2,3], s = [1,1]         输出: 1

  1. class Solution {
  2. public int findContentChildren(int[] g, int[] s) {
  3. Arrays.sort(g);
  4. Arrays.sort(s);
  5. int count = 0;
  6. int j = s.length - 1;
  7. for(int i = g.length - 1; i >= 0; i--){
  8. if(j >= 0 && s[j] >= g[i]){
  9. j--;
  10. count++;
  11. }
  12. }
  13. return count;
  14. }
  15. }
  1. class Solution {
  2. public int findContentChildren(int[] g, int[] s) {
  3. Arrays.sort(g);
  4. Arrays.sort(s);
  5. int count = 0;
  6. int i = 0;
  7. for(int j = 0; j < s.length; j++){
  8. if(i < g.length && s[j] >= g[i]){
  9. i++;
  10. count++;
  11. }
  12. }
  13. return count;
  14. }
  15. }

 376. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

示例:输入:nums = [1,17,5,10,13,15,10,5,16,8]        输出:7
解释:其中一个子序列是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

  1. class Solution {
  2. public int wiggleMaxLength(int[] nums) {
  3. if(nums.length <= 1){
  4. return nums.length;
  5. }
  6. int curDiff = 0; //当前差值
  7. int preDiff = 0; //上一个差值
  8. int count = 1;
  9. for(int i = 1; i < nums.length; i++){
  10. curDiff = nums[i] - nums[i - 1];
  11. //如果当前差值和上一个差值为一正一负(等于0的情况表示初始时的preDiff)
  12. if((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)){
  13. count++;
  14. preDiff = curDiff;
  15. }
  16. }
  17. return count;
  18. }
  19. }

53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。

示例:输入:nums = [-2,1,-3,4,-1,2,1,-5,4]         输出:6

  1. class Solution {
  2. public int maxSubArray(int[] nums) {
  3. int sum = Integer.MIN_VALUE;
  4. int count = 0;
  5. for(int i = 0; i < nums.length; i++){
  6. count += nums[i];
  7. sum = Math.max(sum, count);
  8. if(count <= 0){
  9. count = 0; //重置最大子序起始位置,因为遇到负数一定是拉低总和
  10. }
  11. }
  12. return sum;
  13. }
  14. }

121. 买股票的最佳时机

给定一个数组 prices,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例:输入:[7,1,5,3,6,4]         输出:5

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int low = Integer.MAX_VALUE;
  4. int result = 0;
  5. for(int i = 0; i < prices.length; i++){
  6. low = Math.min(prices[i], low);
  7. result = Math.max(prices[i] - low, result);
  8. }
  9. return result;
  10. }
  11. }

122. 买卖股票的最佳时机 II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。

示例:输入:prices = [7,1,5,3,6,4]         输出:7

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int result = 0;
  4. for(int i = 1; i < prices.length; i++){
  5. result += Math.max(prices[i] - prices[i - 1], 0);
  6. }
  7. return result;
  8. }
  9. }

55. 跳跃游戏

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标。

示例:输入:nums = [2,3,1,1,4]         输出:true

  1. class Solution {
  2. public boolean canJump(int[] nums) {
  3. int coverRange = 0; //初始覆盖范围是0,因为下面的迭代是从下标0开始的
  4. for(int i = 0; i <= coverRange; i++){ //在覆盖范围内更新最大的覆盖范围
  5. coverRange = Math.max(coverRange, i + nums[i]);
  6. if(coverRange >= nums.length - 1){
  7. return true;
  8. }
  9. }
  10. return false;
  11. }
  12. }

45. 跳跃游戏II

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:0 <= j <= nums[i] ,i + j < n;返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。

示例:输入: nums = [2,3,1,1,4]         输出: 2

  1. class Solution {
  2. public int jump(int[] nums) {
  3. int count = 0;
  4. int coverRange = 0; //当前覆盖的最大区域
  5. int maxRange = 0; //最大的覆盖区域
  6. for(int i = 0; i <= maxRange && maxRange < nums.length - 1; i++){
  7. coverRange = Math.max(coverRange, i + nums[i]);
  8. if(i == maxRange){
  9. maxRange = coverRange;
  10. count++;
  11. }
  12. }
  13. return count;
  14. }
  15. }

1005. K 次取反后最大化的数组和

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。重复这个过程恰好 k 次。可以多次选择同一个下标 i 。以这种方式修改数组后,返回数组 可能的最大和 。

示例:输入:nums = [4,2,3], k = 1         输出:5

  1. class Solution {
  2. public int largestSumAfterKNegations(int[] nums, int k) {
  3. Arrays.sort(nums);
  4. // 负数变正数
  5. for(int i = 0; i < nums.length; i++){
  6. if(nums[i] < 0 && k > 0){
  7. nums[i] = -nums[i];
  8. k--;
  9. }
  10. }
  11. // 如果k还大于0,那么反复转变值最小的正数,将k用完
  12. if(k % 2 == 1){
  13. Arrays.sort(nums);
  14. nums[0] = -nums[0];
  15. }
  16. return Arrays.stream(nums).sum();
  17. }
  18. }

134. 加油站

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

示例:输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]         输出: 3

  1. class Solution {
  2. public int canCompleteCircuit(int[] gas, int[] cost) {
  3. int curSum = 0;
  4. int totalSum = 0;
  5. int index = 0;
  6. for(int i = 0; i < gas.length; i++){
  7. curSum += gas[i] - cost[i];
  8. totalSum += gas[i] - cost[i];
  9. if(curSum < 0){
  10. index = i + 1;
  11. curSum = 0;
  12. }
  13. }
  14. if(totalSum < 0){
  15. return -1;
  16. }
  17. return index;
  18. }
  19. }

135. 分发糖果

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:每个孩子至少分配到 1 个糖果,相邻两个孩子评分更高的孩子会获得更多的糖果。请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例:输入:ratings = [1,0,2]         输出:5

  1. class Solution {
  2. public int candy(int[] ratings) {
  3. int[] candy = new int[ratings.length];
  4. candy[0] = 1;
  5. for(int i = 1; i < ratings.length; i++){
  6. if(ratings[i] > ratings[i - 1]){
  7. candy[i] = candy[i - 1] + 1;
  8. }else{
  9. candy[i] = 1;
  10. }
  11. }
  12. for(int i = ratings.length - 2; i >= 0; i--){
  13. if(ratings[i] > ratings[i + 1]){
  14. candy[i] = Math.max(candy[i], candy[i + 1] + 1);
  15. }
  16. }
  17. return Arrays.stream(candy).sum();
  18. }
  19. }

860. 柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。注意,一开始你手头没有任何零钱。给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

示例:输入:bills = [5,5,5,10,20]         输出:true

  1. class Solution {
  2. public boolean lemonadeChange(int[] bills) {
  3. int five = 0;
  4. int ten = 0;
  5. for(int i = 0; i < bills.length; i++){
  6. if(bills[i] == 5){
  7. five++;
  8. }else if(bills[i] == 10){
  9. five--;
  10. ten++;
  11. }else if(bills[i] == 20){
  12. if(ten > 0){
  13. ten--;
  14. five--;
  15. }else{
  16. five -= 3;
  17. }
  18. }
  19. if(five < 0 || ten < 0){
  20. return false;
  21. }
  22. }
  23. return true;
  24. }
  25. }

406. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

示例:输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]        输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]

  1. class Solution {
  2. public int[][] reconstructQueue(int[][] people) {
  3. //身高从大到小排(身高相同k小的站前面)
  4. Arrays.sort(people, (o1, o2) -> {
  5. if(o1[0] == o2[0]){
  6. return o1[1] - o2[1];
  7. }else{
  8. return o2[0] - o1[0];
  9. }
  10. });
  11. List<int[]> list = new LinkedList<>();
  12. for(int[] person : people){
  13. list.add(person[1], person);
  14. }
  15. return list.toArray(new int[people.length][]);
  16. }
  17. }

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

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。

示例:输入:points = [[10,16],[2,8],[1,6],[7,12]]         输出:2

  1. class Solution {
  2. public int findMinArrowShots(int[][] points) {
  3. // 根据气球直径的开始坐标从小到大排序
  4. Arrays.sort(points, (o1, o2) -> Integer.compare(o1[0], o2[0]));
  5. int count = 1; // points不为空至少需要一支箭
  6. for(int i = 1; i < points.length; i++){
  7. if(points[i][0] > points[i - 1][1]){ //气球i和气球i-1不挨着
  8. count++;
  9. }else{
  10. points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
  11. }
  12. }
  13. return count;
  14. }
  15. }

435. 无重复区间

给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。

示例:输入: intervals = [[1,2],[2,3],[3,4],[1,3]]         输出: 1

  1. class Solution {
  2. public int eraseOverlapIntervals(int[][] intervals) {
  3. Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));
  4. int count = 0; // 相交区域的个数
  5. for(int i = 1; i < intervals.length; i++){
  6. if(intervals[i][0] < intervals[i - 1][1]){
  7. intervals[i][1] = Math.min(intervals[i][1], intervals[i - 1][1]);
  8. count++;
  9. }
  10. }
  11. return count;
  12. }
  13. }

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例:输入:intervals = [[1,3],[2,6],[8,10],[15,18]]         输出:[[1,6],[8,10],[15,18]]

  1. class Solution {
  2. public int[][] merge(int[][] intervals) {
  3. //按照左边界排序
  4. Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));
  5. LinkedList<int[]> list = new LinkedList<>();
  6. list.add(intervals[0]);
  7. for(int i = 1; i < intervals.length; i++){
  8. if(intervals[i][0] <= list.getLast()[1]){ //如果左边界大于最大右边界
  9. int start = list.getLast()[0];
  10. int end = Math.max(intervals[i][1], list.getLast()[1]);
  11. list.removeLast();
  12. list.add(new int[]{start, end});
  13. }else{
  14. list.add(intervals[i]);
  15. }
  16. }
  17. return list.toArray(new int[list.size()][]);
  18. }
  19. }
  1. class Solution {
  2. public int[][] merge(int[][] intervals) {
  3. if(intervals.length == 1){
  4. return intervals;
  5. }
  6. Arrays.sort(intervals, ((o1, o2) -> Integer.compare(o1[0], o2[0])));
  7. List<int[]> list = new ArrayList<>();
  8. for(int i = 1; i < intervals.length; i++){
  9. if(intervals[i][0] > intervals[i - 1][1]){
  10. list.add(intervals[i - 1]);
  11. }else{
  12. intervals[i][0] = Math.min(intervals[i - 1][0], intervals[i][0]);
  13. intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]);
  14. }
  15. }
  16. list.add(intervals[intervals.length - 1]); // 添加最后一个
  17. return list.toArray(new int[list.size()][]);
  18. }
  19. }

 763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。返回一个表示每个字符串片段的长度的列表。

示例:输入:s = "ababcbacadefegdehijhklij"         输出:[9,7,8]

  1. class Solution {
  2. public List<Integer> partitionLabels(String s) {
  3. List<Integer> list = new ArrayList<>();
  4. int[] edge = new int[26]; //统计每一个字符最后出现的位置
  5. for(int i = 0; i < s.length(); i++){
  6. edge[s.charAt(i) - 'a'] = i;
  7. }
  8. int index = 0;
  9. int start = -1;
  10. for(int i = 0; i < s.length(); i++){
  11. index = Math.max(index, edge[s.charAt(i) - 'a']);
  12. if(i == index){ //字符最远出现位置下标和当前下标相等,则该点分割点
  13. list.add(i - start);
  14. start = i;
  15. }
  16. }
  17. return list;
  18. }
  19. }

1221. 分割平衡字符串

平衡字符串 中,'L' 和 'R' 字符的数量是相同的。给你一个平衡字符串 s,请你将它分割成尽可能多的子字符串,并满足每个子字符串都是平衡字符串。返回可以通过分割得到的平衡字符串的 最大数量 

示例:输入:s = "RLRRLLRLRL"   输出:4   解释:s 可以分割为 "RL"、"RRLL"、"RL"、"RL"

  1. class Solution {
  2. public int balancedStringSplit(String s) {
  3. int count = 0;
  4. int sumL = 0;
  5. int sumR = 0;
  6. for(int i = 0; i < s.length(); i++){
  7. if(s.charAt(i) == 'L'){
  8. sumL++;
  9. }else if(s.charAt(i) == 'R'){
  10. sumR++;
  11. }
  12. if(sumL == sumR){
  13. count++;
  14. }
  15. }
  16. return count;
  17. }
  18. }

 738. 单调递增的数字

当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。

示例:输入: n = 10         输出: 9

  1. class Solution {
  2. public int monotoneIncreasingDigits(int n) {
  3. String s = String.valueOf(n);
  4. char[] chars = s.toCharArray();
  5. int start = s.length();
  6. for(int i = s.length() - 2; i >= 0; i--){
  7. if(chars[i] > chars[i + 1]){
  8. chars[i]--;
  9. start = i + 1;
  10. }
  11. }
  12. for(int i = start; i < s.length(); i++){
  13. chars[i] = '9';
  14. }
  15. return Integer.parseInt(String.valueOf(chars));
  16. }
  17. }

649. Dota2参议院

示例:输入:senate = "RD"         输出:"Radiant"

  1. class Solution {
  2. public String predictPartyVictory(String senate) {
  3. Queue<Integer> radiant = new LinkedList<>();
  4. Queue<Integer> dire = new LinkedList<>();
  5. for(int i = 0; i < senate.length(); i++){
  6. if(senate.charAt(i) == 'R'){
  7. radiant.offer(i);
  8. }else{
  9. dire.offer(i);
  10. }
  11. }
  12. while(!radiant.isEmpty() && !dire.isEmpty()){
  13. int radiantIndex = radiant.poll();
  14. int direIndex = dire.poll();
  15. if(radiantIndex < direIndex){
  16. radiant.offer(radiantIndex + senate.length());
  17. }else{
  18. dire.offer(direIndex + senate.length());
  19. }
  20. }
  21. return radiant.isEmpty() ? "Dire" : "Radiant";
  22. }
  23. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/390560
推荐阅读
相关标签
  

闽ICP备14008679号