LeetCode Day29|●理论基础(局部最优推出全局最优)●455.分发饼干(大饼干尽量去喂大胃口、小饼干能满足一个小孩就满足一个小孩)●376. 摆动序列(两种平坡)●53. 最大子序和

day29-1 ●理论基础

什么是贪心

局部最优求全局最优

两个极端

常识性的东西也有方法论

贪心套路

贪心无套路
想局部最优即可
数学归纳、反证法
需要数学证明的题目:环形链表||

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){// 有环
            	// 找环的入口
                ListNode index1 = fast;
                ListNode index2 = head;
                while(index1 != index2){
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

硬生生想出来的套路:

  • 将问题拆分为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个问题的最优解
  • 将局部最优解堆叠成全局最优解

总结

局部最优得全局最优
有两个极端,所以不要轻视
常识性推导+举反例

day29-2 ●455.分发饼干

解题思路

局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。
大饼干尽量去喂大胃口的孩子

其他思路:小饼干能满足一个小孩就满足一个小孩

代码实现

class Solution {
    // 大饼干尽量去满足大胃口
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int count = 0;// 统计可以满足的孩子数
        int start = s.length - 1;
        for(int index = g.length - 1; index >= 0; index--){
            if(start >= 0 && g[index] <= s[start]){
                count++;
                start--;
            }
        }
        return count;
    }
}
class Solution {
	// 小饼干能满足一个小孩子就满足一个小孩子
    public int findContentChildren(int[] g, int[] s) {// g:胃口  s:饼干
        Arrays.sort(g);
        Arrays.sort(s);
        int count = 0;
        int start = 0;
        for(int index = 0; index < s.length; index++){
            if(start < g.length && s[index]>= g[start]){
                count++;
                start++;
            }
        }
        return count;
    }
}

遍历顺序

大饼干尽量去喂大胃口的孩子:倒序
小饼干能满足一个小孩就满足一个小孩:正序

day29-3 ●376. 摆动序列

解题思路

上下有平坡

在这里插入图片描述

收尾元素

代码实现

class Solution {
    // 当出现摆动的时候再去更新prediff,可以绕过有单调有平坡的情况
    public int wiggleMaxLength(int[] nums) {
        if(nums.length <= 1){
            return nums.length;
        }
        int curDiff = 0;// 当前差值
        int preDiff = 0;// 上一个差值
        int count = 1; // 末尾也算一个
        for(int i = 1; i < nums.length; i++){
            curDiff = nums[i] - nums[i - 1];
            if((preDiff<=0&&curDiff>0)||(preDiff>=0&&curDiff<0)){
                count++;
                // 当出现摆动的时候再去更新prediff,可以绕过有单调有平坡的情况
                preDiff = curDiff;
            }
        }
        return count;
    }
}

单调有平坡

在这里插入图片描述

总结

要考虑:1.上下有平坡、2.单调有平坡的情况

day29-4 ●53. 最大子序和

解题思路

只要前面的连续和不为负数都有可能让后面的数变大
如果前面的连续后为负的话就立刻抛弃选择下一个位置作为我们的起始位置

模拟过程

在这里插入图片描述

代码实现

class Solution {
    public int maxSubArray(int[] nums) {
        int result = Integer.MIN_VALUE;
        int  count = 0 ;// 前面的连续和
        for(int i = 0; i < nums.length; i++){
            count += nums[i];
            // 统计最大值
            if(count>result){
                result = count;
            }
            // 如果前面的连续和为负,对整体值没有贡献,直接舍弃
            if(count<0){
                count=0;
            }
        }
        return result;
    }
}

总结

想清楚贪心贪的是哪里,局部最优是哪里
不是遇到负数就跳过而是前面的连续和为负数我们才选择下一个元素作为我们的起点

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值