Leetcode数据结构入门第三天(数组)

350. 两个数组的交集 II

题目描述

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

样例

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

思路

这里是要求解两个数组的交集,但是并不是传统意义上的数列的交集,只要两个数组中有重复的元素都可以取出来,但是交集中的元素出现的次数必须跟原来两个数组中重复出现次数一致(取较小值)
为了避免重复输出,这里先对这两个数组进行排序,然后利用双指针进行遍历两个数组,分别判断两个指针对应的元素大小关系,如果数组1中元素比数组2的当前元素小,说明当前元素不会出现在交集中,跳过,指针1++,指向下一个元素;同理对于数组2也是这样,;如果元素相等,把元素压入交集中,两个指针同时指向下一个元素。循环结束的条件是两个其中一个数组走到了尽头,就可以结束啦!!

参考代码

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        int n1=nums1.size();
        int n2=nums2.size();
        int p1=0,p2=0;//双指针
        //先排序然后利用双指针遍历
        sort(nums1.begin(),nums1.end());
        sort(nums2.begin(),nums2.end());
        vector<int> res;
        //排完序后的数组求交集比较好,因为这样可以避免重复输出交集中的元素
        while(p1<n1&&p2<n2)
        {
            //如果数组1中元素比数组2的当前元素小,说明前面元素不会出现在交集中,跳过
            if(nums1[p1]<nums2[p2])
            {
                p1++;
            }//对于数组2也是一样
            else if(nums1[p1]>nums2[p2])
            {
                p2++;
            }
            else//直到找到相同元素,压入结果中,两个数组指针同时指向下一个元素。
            {
                res.push_back(nums1[p1]);
                p1++;
                p2++;
            }
        }
        return res;
        
    }
};

121. 买卖股票的最佳时机

题目描述

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

样例

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0

思路一

PS:这里最容易想到的就是两层循环的暴力破解法,当我满怀欢喜写上去的时候运行超时。。。当然在意料之中!!只能优化算法呗,这里很容易想起前面做过的最大子数组和问题,当时使用的就是动态规划法,动态转移方程就是
第i天卖出的最大利润(dp[i])=第i-1天的最大利润加上价格差价(当天与前一天价格差),这里只需要保证dp[i]为正即可。然后不断更新最大值,一趟循环后就是最大利润

对比一下:最大子数组和

参考代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        //动态规划
        int maxn=0;
        int n=prices.size();
        //前一天卖出可以获得的最大利润
        int pre=0;
        for(int i=1;i<n;i++)
        {
            //状态转移方程:第i天的利润=前一天的最大利润加上利润差
           pre=max(pre+prices[i]-prices[i-1],0);
           maxn=max(maxn,pre);
        }
        return maxn;
    }
};

思路二

其实本质也是动态规划,但是更容易想到和理解。我们要求的是最大利润,所以求出第i天卖出与前i天中最低点买入的价格差即求出利润,然后不断更新最大值即可。
这里dp[i]表示的是前i天的最低价格,我们先求出前i天卖出的最低价格,然后比较第i天卖出的价格减去最低价格与现在的最大利润,更新最大值。

第i天以前(包括第i天)的最低点和i-1天的最低点有关,其动态转移方程如下:
dp[i] = min(dp[i-1],prices[i])
其中dp[0]=prices[0],然后动态计算之后的就可以了。 得到了前i天的最低点以后,只需要维护一个max用来保存最大收益就可以了。 这个时候是空间复杂度O(n)的动态规划,正常代码如下:

  //dp[i]表示截止到i,价格的最低点是多少   dp[i]=min(dp[i-1],nums[i])
        int maxn = 0;
        int* dp = new int[prices.size()];
        dp[0] = prices[0];
        for (int i = 1; i < prices.size(); i++) 
        {
            dp[i] = min(dp[i-1],prices[i]);
            maxn = max(prices[i] - dp[i],maxn); 
        }
        return maxn;

考虑优化空间,仔细观察动态规划的辅助数组,其实每一次只用到了一个空间dp[i],因此可以把dp数组改成单个变量min_price来存储截止到第i天的最低价格。优化之后的代码如下:。

参考代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        //动态规划2:
        int maxn=0;
        int min_price=99999;//注意这里最小值初始化要足够大
        int n=prices.size();
        //我们要求的是最大利润,所以求出第i天卖出与前i天中最低点买入的价格差,然后不断更新最大值即可。
        //这里dp[i]表示的是前i天的最低价格:dp[i]=min(dp[i-1],prices[i])
        for(int i=0;i<n;i++)
        {
			min_price=min(min_price,prices[i]);//前i天的最低价格,求dp[i]
            maxn=max(maxn,prices[i]-min_price);//最大利润更新
        }
      
        return maxn;
    }
};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值