力扣● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和

● 455.分发饼干

遍历小孩胃口,对每个小孩,选择符合他胃口的最小尺寸的饼干。这里如果g不排序,index每轮都要从0开始,时间复杂度会到平方。

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int count=0;
        sort(s.begin(),s.end());
        sort(g.begin(),g.end());
        int index=0;
        for(int i=0;i<g.size();++i){
            for(;index<s.size()&&g[i]>s[index];++index);//s[index]:满足胃口最小的饼干       
            if(index==s.size())break;
            index++;
            count++;
        }
        return count;
}
};

● 376. 摆动序列

峰值是摆动的不能删。这题就是统计所有峰值(两边的两个元素和中间的极值)。

自己没看随想录写了一下。pre统计相邻前一个间隔的差值,p统计当前间隔的差值。如果p==0,或者前后两个间隔差值符号相反count不会++。但是有2个数据很多的例子不能通过:

class Solution {//不可通过
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size()==1)return 1;
        if(nums.size()==2&&nums[0]==nums[1])return 1;//2个相同元素
        int pre=nums[1]-nums[0];//前一个间隔的差值
        int count=(pre==0)?1:2;//nums前两个里面的count
        for(int i=2;i<nums.size();++i){
            int p=nums[i]-nums[i-1];
            if(p==0||p * pre < 0){    //不应该统计
                pre=p;                //wrong
                continue;
            }
            else{
                pre=p;
                count++;
            }
        }
        return count;
    }
};

发现问题:我是把不符合这四种情况的直接跳过,p==0(目前平缓)和p*pre>0(单调增或单调减)是不应该统计的情况。我这里错在,不应该统计的情况下,不能把pre赋值为p,直接continue就行,这个pre应该指向上一个不平缓的间隔,不是每一次都要更新。

pre不一定得是p的前一个相邻的间隔,而是应该是p的前一个不平缓的间隔(上升或者下降),比如这个例子,如果pre一直在p的前面,到3的时候p>0、pre=0就会统计上,但是这个正确答案应该是 最后一个不统计,所以p(3-2)应该和(2-1,p的前一个不平缓的间隔)比,而不是相邻前一个

改一改代码如下(可通过),这样pre永远不会赋值为0,所以一直是p的前一个不平缓间隔的差值。

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size()==1)return 1;
        int pre=nums[1]-nums[0];//前一个不平缓间隔的差值,不是相邻!!
        int count=(pre==0)?1:2;//先统计nums前两个元素的count
        for(int i=2;i<nums.size();++i){
            int p=nums[i]-nums[i-1];
            if(p==0||p * pre > 0){      //不统计的情况
                //pre=p;        //pre不会=0
                continue;
            }
            pre=p;
            count++;
        }
        return count;
    }
};

所以严格单调递减/严格单调递增和中间有相同元素的递增或者递减都会跳过,这样把所有峰值都统计到了。下面图里面没有峰值,所以不会统计。

● 53. 最大子序和

暴力超时了。

自己想的:sum跳过负数nums[i];正确的:nums[i]跳过负数sum。所以i从左往右:一旦sum为负数,drop it。即sum置零,重新求和。就是把nums[i]作为基准量,sum作为偏移量,抛弃会使得nums[i]变小的sum(小于0的)。每个i都会记录下max_sum,选出最大sum

和上一道题代码都短,就是想不到这种思路。

如果都是负数,可以在循环前求出序列的最大值,然后返回,这样时间开销稍微大一点。

或者在循环的时候,先比较出max_sum,再判断sum是不是负数是否要置零,这样max_sum放的就是最大值,无论这个nums是只有负数还是正负数都有

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int max_sum=INT_MIN;

        int sum=0;
        for(int i=0;i<nums.size();++i){
            if(sum<0){
                sum=0;                   //判断sum要不要置零(重新开始)
            } 
            sum+=nums[i];                    //sum:某个元素到nums[i]的和
            if(sum>max_sum)max_sum=sum; //每个元素i都对应一个sum,都与max_sum比较以更新max_sum 
                               
        }
        return max_sum;
    }
};

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值