力扣初级算法练习day01


前言

来了实验室,挺安静,这么安静的环境就得思考点事情。


一、删除排序数组中的重复项

题目:给你一个 升序排列的数组 nums ,请原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。元素的相对顺序应该保持 一致。

摘要:升序的数组、原地删除、删除重复元素使每个元素只出现一次、元素的相对位置不能变、返回新长度

原思想:两个指针,一个控制左边、一个控制右边,如果左指针指向元素和右指针指向元素相同,那么右指针指向下一个元素,左指针也指向下一个元素,当左右指针指向元素不同时,使右指针指向元素覆盖左指针指向元素;

原代码

class Solution {
    public int removeDuplicates(int[] nums) {
        int i = 0;

        for (int j = 1; j < nums.length; j++) {
            if (nums[i] != nums[j]) {
                nums[i] = nums[j];
            }
            i++;
        }

        return i + 1;
    }
    }

问题:应该在遇到左右指针不一致时,才移动左指针,比如输入的数组是[1,1,1,2],这样的话输出的数组是[1,1,2];没有实现删除重复元素的目的

新思想:还是左右指针,右边做检查,左边不动,只有当左右指针指向元素不同时,才使左指针+1,并将右指针指向元素替换左指针指向元素

新代码:

class Solution {
    public int removeDuplicates(int[] nums) {
        int i = 0;

        for (int j = 1; j < nums.length; j++) {
            if (nums[i] != nums[j]) {
                i++;
                nums[i] = nums[j];
            }
        }
        return i + 1;
    }
    }

二、买卖股票的最大时机2

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

摘要:prices[i]是某支股票第i天的价格、每天只能购买或卖出股票、看怎么买入卖出能收获这几天内的最大利润、返回最大利润

原想法:按数组一个一个循环,也就是第一次,从第0个开始,循环后面的数组,找到这一次循环的最大值,然后从第1个开始,循环后面的数组,找到这一次循环的最大值,并和上一次循环的最大值比较,如果比它大就替换,否则保留,依次往后。

原代码

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

问题:每次循环只是单词循环的最大,没有考虑到卖出之后又买入的可能,比如[7,1,6,3,5],股民完全可以在1买入6卖出,再3买入,5卖出,收获最大利益,而不是1买入后6卖出就不管了

新思想
1.要考虑股票这类问题的性质,获得最大收益就是在最低点买入,最高点卖出,每次都这样,就可以收获最大利润,也就是说,我买入的阶段都是在上涨阶段
股票图片
2.这里涉及一个算法:贪心算法
贪心算法是指:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解
也就是说,我一段时期的最大收益,可以考虑每个局部的最大收益之和;
对于这道题来说,就是前后元素相减,为正数的值之和;
在这里插入图片描述
对于1思想的新代码

public int maxProfit(int[] prices) {
    if (prices == null || prices.length < 2)
        return 0;
    int total = 0, index = 0, length = prices.length;
    while (index < length) {
        //如果股票下跌就一直找,直到找到股票开始上涨为止
        while (index < length - 1 && prices[index] >= prices[index + 1])
            index++;
        //股票上涨开始的值,也就是这段时间上涨的最小值
        int min = prices[index];
        //一直找到股票上涨的最大值为止
        while (index < length - 1 && prices[index] <= prices[index + 1])
            index++;
        //计算这段上涨时间的差值,然后累加
        total += prices[index++] - min;
    }
    return total;
}

对于2思想的新代码

public int maxProfit(int[] prices) {
    int total = 0;
    for (int i = 0; i < prices.length - 1; i++) {
        //原数组中如果后一个减去前一个是正数,说明是上涨的,
        //我们就要累加,否则就不累加
        //Math.max(x,y)返回x和y中的较大值
        total += Math.max(prices[i + 1] - prices[i], 0);
    }
    return total;
}

总结

1.先加再操作,还是操作完加,还是到操作的时候再加,是不同的场景,
for(xxx++)肯定是每次都加 {
if(){xxx+ 再操作}//到满足条件操作的时候才进行

if(){操作完 xxx+}//到满足条件操作的时候再进行

xxx++每次循环都加一次
}
2.一个问题拿住,先提取关键字,搞清楚问什么要什么,有什么约束
3.然后要想这个问题有什么特点,比如股票的特点,最低最高,重复项的特点,一次重复还是多次重复,隔三岔五重复还是连续重复
4.先有思路然后写代码,写代码中再想思路;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值