LeetCode 热题 100-贪心算法

贪心算法-LeetCode 热题 100

本质:局部最优(每次)→全局最优(最终)。

2789. 合并后数组中的最大元素

class Solution {
    public long maxArrayValue(int[] nums) {
        // 题意:左边的元素要小于它右边的元素,将右边的元素替换为二者之和,删去左边的元素
        // 只用sum记录当前数组中的最大值,但是不改变原数组
        long sum = nums[nums.length - 1];
        for (int i = nums.length - 2; i >= 0; i--) {
            if (nums[i] <= sum)// 当前元素是否小于sum(合并后的数)
                sum = nums[i] + sum;// 是,则合并
            else
                sum = nums[i];// 否,将sum更新为当前元素
        }
        return sum;
    }
}

455. 分发饼干

class Solution {
    // g是每个孩子的胃口,s是饼干大小
    // "每个孩子最多只能给一块饼干"
    public int findContentChildren(int[] g, int[] s) {
        // 思路:按孩子胃口从小到大的顺序依次满足每个孩子,且对于每个孩子,选择可以满足这个孩子的胃口且尺寸最小的饼干。
        Arrays.sort(g);
        Arrays.sort(s);
        int child = 0;// 能吃饱的孩子的数量,g数组的指针
        int cookie = 0;// 饼干数组的指针,s数组的指针
        while (child < g.length && cookie < s.length) {
            if (g[child] <= s[cookie])
                child++;// 只有当前的饼干能够满足孩子的胃口,孩子指针才向后移
            cookie++;// 无论这块饼干有没有分配给孩子,都要向后移
        }
        return child;
    }
}

121. 买卖股票的最佳时机

class Solution {
    public int maxProfit(int[] prices) {
        // 思路:低买高卖就能赚钱
        // 历史最低价格 minprice,假设自己的股票是在那天买的。
        // 那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice
        int minprice = Integer.MAX_VALUE;//历史最低价
        int maxprofit = 0;//最大利润值
        for (int i = 0; i < prices.length; i++) {
            if (prices[i] < minprice)//如果当前价格比历史最低价还低
                minprice = prices[i];// 更新历史最低价
            else if (prices[i] - minprice > maxprofit)//如果我在这天卖出,获得的利润大于我之前能获得的最大利润
                maxprofit = prices[i] - minprice;// 更新最大利润值
        }
        return maxprofit;
    }
}

55. 跳跃游戏

class Solution {
    // 任意一个位置 y,要存在一个位置 x,它本身可以到达&&x+numx[x]>=y,y则可以到达
    public boolean canJump(int[] nums) {
        int rightmost = 0;// 最远可到达的位置
        int n = nums.length;
        //如果第一个元素为0,可根据数组长度直接进行判断
        if (nums[0] == 0) {
            if (nums.length == 1)
                return true;
            else
                return false;
        }

        for (int i = 0; i < n; ++i) {
            if (i <= rightmost) {// 如果当前位置可达
                rightmost = Math.max(rightmost, i + nums[i]);// 最远可到达的位置
                if (rightmost >= n - 1)// 如果最远可到达的位置到达了数组末尾
                    return true;
            }
        }
        return false;
    }
}

45. 跳跃游戏 II

class Solution {
    public int jump(int[] nums) {
        int n = nums.length;// 数组长度
        int rightmost = 0;// 目前能跳到的最远位置

        int steps = 0;// 跳跃步数
        int end = 0;// 上次跳跃可达范围右边界(下次的最右起跳点)
        
        for (int i = 0; i < n - 1; ++i) {
            if (i <= rightmost) {// 如果当前位置可达
                rightmost = Math.max(rightmost, i + nums[i]);// 更新 最远可到达的位置
                // 到达上次跳跃能到达的右边界了
                if (i == end) {
                    end = rightmost;// 目前能跳到的最远位置变成了下次起跳位置的右边界
                    steps++; // 进入下一次跳跃
                }
            }
        }
        return steps;
    }
}

763. 划分字母区间

class Solution {
    public List<Integer> partitionLabels(String s) {
        int[] maxPosition = new int[26];// 记录每个字母出现的最远位置
        List<Integer> result = new ArrayList<>();// 记录切分后的结果[9,7,8]

        for (int i = 0; i < s.length(); i++) {
            maxPosition[s.charAt(i) - 'a'] = i;
        }

        // for (int i = 0; i < maxPosition.length; i++) {
        // System.out.println((char) (i + 'a') + "=" + maxPosition[i]);
        // }

        int start = 0;// 待切割的起始位置
        int scannedCharMaxPos = 0;// 已扫描的字符中最远的位置
        // 开始切割
        for (int i = 0; i < s.length(); i++) {
            int curCharMaxPos = maxPosition[s.charAt(i) - 'a']; // 当前扫描的字符的最远位置
            scannedCharMaxPos = Math.max(scannedCharMaxPos, curCharMaxPos); // 更新「已扫描的字符中最远的位置」
            if (i == scannedCharMaxPos) { // 正好扫描到「已扫描的字符的最远位置」,到达切割点
                result.add(i - start + 1);// 此次切割长度
                start = i + 1;// 更新,下一个待切割的字符串的起始位置
            }
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值