数据结构刷题:第三天

简介: 由于同一个数字在两个数组中都可能出现多次,因此需要用哈希表存储每个数字出现的次数。对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。

一,两个数组的交集:


350. 两个数组的交集 II - 力扣(LeetCode)

https://leetcode.cn/problems/intersection-of-two-arrays-ii/

1e9fe9ec8c28402bab0e01feb2375f40.png


1,哈希表:


由于同一个数字在两个数组中都可能出现多次,因此需要用哈希表存储每个数字出现的次数。对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。


首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数,然后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数。


为了降低空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数,然后遍历较长的数组得到交集。


//哈希表存储数组1的值和出现次数,然后遍历数组2
class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int,int> mp;
        for (int i = 0; i < nums1.size(); i++) {
           mp[nums1[i]]++; 
        }
        vector<int> ans;
        for (int i = 0; i < nums2.size(); i++) {
            if (mp[nums2[i]]) {
                ans.push_back(nums2[i]);
                mp[nums2[i]]--;
            }
        }
        return ans;
    }
};


复杂度分析


●时间复杂度: O(m+n),中m和n分别是两个数组的长度。需要遍历两个数组并对哈希表进行操作,哈希表操作的时间复杂度是0(1),因此总时间复杂度与两个数组的长度和呈线性关系。

●空间复杂度: O(min(m,n)), 其中m和n分别是两个数组的长度。对较短的数组进行哈希表的操作,哈希表的大小不会超过较短的数组的长度。为返回值创建一个 数组intersection ,其长度为较短的数组的长度。


2,排序+双指针:


如果两个数组是有序的,则可以使用双指针的方法得到两个数组的交集。


首先对两个数组进行排序,然后使用两个指针遍历两个数组。


初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,将该数字添加到答案,并将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。


//两个数组排好序后,依次比较大小,遇到相同的放入答案数组
class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        vector<int> ans;
        int left=0, right=0;
        while(left < nums1.size() && right < nums2.size()){
            if (nums1[left] < nums2[right]) {
                left++;
            } else if(nums1[left] > nums2[right]) {
                right++;
            } else{
                ans.push_back(nums1[left]);
                left++;
                right++;
            }
        }
        return ans;
    }
};


复杂度分析


●时间复杂度: O(mlogm + nlogn), 中m和n分别是两个数组的长度。对两个数组进行排序的时间复杂度是O(m logm + n logn),遍历两个数组的时间复杂度是O(m + n),因此总时间复杂度是O(mlogm + n log n)。


●空间复杂度: 0(min(m,n)), 其中m和n分别是两个数组的长度。为返回值创建一 个数组

intersection ,其长度为较短的数组的长度。不过在C++中,我们可以直接创建一个vector,不需要把答案临时存放在-个额外的数组中,所以这种实现的空间复杂度为0(1)。


结语


如果nums2的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中。 那么就无法高效地对nums2进行排序,因此推荐使用方法一而不是方法二。在方法一中,nums2 只关系到查询操作,因此每次读取nums2中的一部分数据,并进行处理即可。


,买卖股票的最佳时机


121. 买卖股票的最佳时机 - 力扣(LeetCode)

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/

6dd8bef0f66a41ee97de97e47dcde6ac.png


1,动态规划:


假设给定的数组为: [7, 1, 5,3, 6, 4]

如果我们在图表上绘制给定数组中的数字,我们将会得到:


fd00483c5a484fe38348573247460242.png


我们来假设自己来购买股票。随着时间的推移,天我们都可以选择出售股票与否。那么,假设在第i天,如果我们要在今天卖股票,那么我们能赚多少钱呢?显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录-个历史最低价格minprice ,我们就可以假设自己的股票是在那天买的。那么我们在第i天卖出股票能得到的利润就是prices[i] 一minprice。


因此,我们只需要遍历价格数组一遍,记录历史最低点,然后在每一天考虑这么一个问题:如果我是在历史最低点买进的,那么我今天卖出能赚多少钱?当考虑完所有天数之时,我们就得到了最好的答案。


class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int inf = 1e9;
        int minprice = inf, maxprofit = 0;
        for (int price: prices) {
            maxprofit = max(maxprofit, price - minprice);
            minprice = min(price, minprice);
        }
        return maxprofit;
    }
};


复杂度分析


  • 时间复杂度:O(n),只需要遍历一次。
  • 空间复杂度:O(1),只使用了常数个变量。


以上部分来自力扣由本人整理而来。

目录
相关文章
|
编译器 C语言
【数据结构刷题】消失的数字和轮转数组(下)
【数据结构刷题】消失的数字和轮转数组(下)
【数据结构刷题】消失的数字和轮转数组(上)
【数据结构刷题】消失的数字和轮转数组(上)
|
算法
数据结构刷题训练:用栈实现队列(力扣OJ)
数据结构刷题训练:用栈实现队列(力扣OJ)
72 0
|
7月前
|
存储 算法 C语言
【数据结构与算法 刷题系列】合并两个有序链表
【数据结构与算法 刷题系列】合并两个有序链表
|
7月前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
7月前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
7月前
|
算法
【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)
【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)
|
7月前
|
算法
【数据结构与算法 刷题系列】判断链表是否有环(图文详解)
【数据结构与算法 刷题系列】判断链表是否有环(图文详解)
|
7月前
|
算法
【数据结构与算法 刷题系列】移除链表元素
【数据结构与算法 刷题系列】移除链表元素