贪心算法思想

贪心算法思想

  • leetcode455. 分发饼干
  • leetcode1005. K 次取反后最大化的数组和
  • leetcode376. 摆动序列
  • leetcode738. 单调递增的数字
  • leetcode122. 买卖股票的最佳时机 II
  • leetcode714. 买卖股票的最佳时机含手续费
  • leetcode406. 根据身高重建队列
  • leetcode135. 分发糖果
  • leetcode55. 跳跃游戏
  • leetcode45. 跳跃游戏 II
  • leetcode435. 无重叠区间
  • leetcode452. 用最少数量的箭引爆气球
  • leetcode968. 监控二叉树
  • leetcode134. 加油站

leetcode455. 分发饼干

贪心算法思想_第1张图片
贪心算法思想_第2张图片

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

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

贪心算法思想_第3张图片
贪心算法思想_第4张图片

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        Arrays.sort(nums);
        int sum = 0, i;
        for (i = 0; i < nums.length && nums[i] < 0 && i < k; i++) {
            nums[i] = -nums[i];
        }
        Arrays.sort(nums);
        for (int val : nums) sum += val;
        if (((k - i) & 1) == 0) return sum;
        return sum - 2 * nums[0];
    }
}

leetcode376. 摆动序列

贪心算法思想_第5张图片
贪心算法思想_第6张图片

class Solution {
    public int wiggleMaxLength(int[] nums) {
        if (nums.length <= 1) return nums.length;
        return Math.max(process(nums, true), process(nums, false));
    }

    private int process(int[] nums, boolean flag) {
        int i = 1, res = 0;
        while (i < nums.length) {
            if (flag) while (i < nums.length && nums[i] >= nums[i - 1]) i++;
            else while (i < nums.length && nums[i] <= nums[i - 1]) i++;
            flag = !flag;
            res++;
        }
        return res;
    }
}

leetcode738. 单调递增的数字

贪心算法思想_第7张图片
贪心算法思想_第8张图片

class Solution {
    /**
     * 思路:
     *  从右向左扫描数字,若发现当前数字比其左边一位(较高位)小,
     *  则把其左边一位数字减1,并将该位及其右边的所有位改成9
     * 不能从左向右,因为先处理高位,低位的改变可能不满足高位较小的条件了
     */
    public int monotoneIncreasingDigits(int N) {
        String num = String.valueOf(N);
        char[] arr = num.toCharArray();
        int len = arr.length;
        if (len < 2) return N;
        int pre = len;
        for (int i = len - 2; i >= 0; i--) {
            if (arr[i] > arr[i + 1]) {
                arr[i]--;
                for (int j = i + 1; j < pre; j++) {
                    arr[j] = '9';
                }
                pre = i + 1;
            }
        }
        return Integer.parseInt(new String(arr));
    }
}

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

贪心算法思想_第9张图片
贪心算法思想_第10张图片
贪心题目思路讲解

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

leetcode714. 买卖股票的最佳时机含手续费

贪心算法思想_第11张图片
贪心算法思想_第12张图片
贪心算法思想_第13张图片

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int profit = 0;//盈利
        int buy = Integer.MAX_VALUE;//股票买入时的价格
        for (int i = 0; i < prices.length - 1; ++i) {
            buy = Math.min(prices[i] + fee, buy);//令股票买入的时的价格最低
            if (prices[i + 1] > buy) {//明天卖出股票有盈利,立刻卖出,并更新盈利
                profit += (prices[i + 1] - buy);
                //一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
                buy = prices[i + 1];//更新股票买入时的价格,不用手续费
            }
        }
        return profit;
    }
}

leetcode406. 根据身高重建队列

贪心算法思想_第14张图片
贪心算法思想_第15张图片

  • 身高降序,位次升序
class Solution {
    public int[][] reconstructQueue(int[][] people) {
        int N = people.length;
        Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]);
        List<int[]> list = new ArrayList<>(N);
        for (int[] val : people) list.add(val[1], val);
        return list.toArray(new int[N][2]);
    }
}

leetcode135. 分发糖果

贪心算法思想_第16张图片
贪心算法思想_第17张图片

class Solution {
    public int candy(int[] ratings) {
        int[] candy = new int[ratings.length];
        Arrays.fill(candy, 1);
        // 满足左
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] > ratings[i - 1]) {
                candy[i] = candy[i - 1] + 1;
            }
        }
        // 满足右侧并取左右最大值
        for (int i = ratings.length - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candy[i] = Math.max(candy[i], candy[i + 1] + 1);
            }
        }
        // 加和记录结果
        int count = 0;
        for (int value : candy) {
            count += value;
        }
        return count;
    }
}

leetcode55. 跳跃游戏

贪心算法思想_第18张图片
贪心算法思想_第19张图片

  • 和后面的加油站题思路基本一样
class Solution {
    public boolean canJump(int[] nums) {
        int pre = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i > pre) return false;
            pre = Math.max(pre, i + nums[i]);
        }
        return true;
    }
}

leetcode45. 跳跃游戏 II

贪心算法思想_第20张图片
贪心算法思想_第21张图片

  • 和加油站相似,加油站是路过加油站的油量最大值(堆),这是坐标向右伸展的最大值(可以用堆,不过我们只是需要最大值,所以没必要)
class Solution {
    public int jump(int[] nums) {
        if (nums.length <= 1) return 0;
        int thisL = nums[0], res = 1, index = 0, maxL = thisL;
        while (thisL < nums.length - 1) {
            while (index <= thisL) {
                maxL = Math.max(maxL, index + nums[index++]);
            }
            if (thisL >= maxL) return 0;
            thisL = maxL;
            res++;
        }
        return res;
    }
}

leetcode435. 无重叠区间

贪心算法思想_第22张图片
贪心算法思想_第23张图片

  • 重复的话就删除结尾大的
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals, (o1, o2) ->  o1[0] - o2[0]);
        int res = 0, pre = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            if (pre > intervals[i][0]) {
                pre = Math.min(pre, intervals[i][1]);
                res++;
            } else {
                pre = intervals[i][1];
            }
        }
        return res;
    }
}

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

贪心算法思想_第24张图片
贪心算法思想_第25张图片

class Solution {
    public int findMinArrowShots(int[][] points) {
        int N = points.length;
        if (N <= 1) return N;
        Arrays.sort(points, Comparator.comparingInt(o -> o[0]));
        int res = 1, pre = points[0][1];
        for (int i = 1; i < N; i++) {
        	// 当前剑位置转移
            if (points[i][0] <= pre) pre = Math.min(pre, points[i][1]);
            else {// 新剑更新
                res++;
                pre = points[i][1];
            }
        }
        return res;
    }
}

leetcode968. 监控二叉树

贪心算法思想_第26张图片
贪心算法思想_第27张图片

  • 主要是节点状态的表示:
    • 0:表示当前节点没有照亮
    • 1:表示当前节点被照亮但是没有灯
    • 2:当前节点有灯
class Solution {
    int res = 0;

    public int minCameraCover(TreeNode root) {
        if (root == null) return res;
        if (process(root) == 0) res++;
        return res;
    }

    private int process(TreeNode root) {
        if (root == null) return 1;
        int left = process(root.left);
        int right = process(root.right);
        if (left == 0 || right == 0) {// 子节点有一个暗就必须有该节点放灯
            res++;
            return 2;
        }
        if (left == 1 && right == 1) {// 若左右均是被照亮的,那么就返回0,表示要等待上层节点的灯被照亮
            return 0;
        }
        // 左或右存在一个灯,并且都不是暗灯
        return 1;
    }
}

leetcode134. 加油站

贪心算法思想_第28张图片
贪心算法思想_第29张图片

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int curSum = 0;
        int totalSum = 0;
        int index = 0;
        for (int i = 0; i < gas.length; i++) {
            curSum += gas[i] - cost[i];// 累计和
            totalSum += gas[i] - cost[i];
            if (curSum < 0) {// 剩余油量累计小于0,说明不能下一路了,就从下一个位置开始
                index = (i + 1) % gas.length;
                curSum = 0;
            }
        }
        // 若油量有剩余说明总有结果,那么curSum更新的充要条件也满足了
        return totalSum < 0 ? -1 : index;
    }
}

你可能感兴趣的:(贪心算法,算法,排序算法,leetcode,java)