数据结构刷题:第三天

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

一,两个数组的交集:


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),只使用了常数个变量。


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

目录
相关文章
|
6天前
|
算法 存储 机器学习/深度学习
【数据结构】——期末复习题库(6)
【数据结构】——期末复习题库(6)
38 3
【数据结构】——期末复习题库(6)
|
6天前
|
存储 算法 调度
数据结构期末复习(3)栈和队列
数据结构期末复习(3)栈和队列
21 0
|
机器学习/深度学习 算法 索引
数据结构刷题篇:第二天
数据结构刷题篇:第二天
59 0
数据结构刷题篇:第二天
|
机器学习/深度学习 算法 C++
数据结构刷题:第四天
数据结构刷题:第四天
68 0
数据结构刷题:第四天
|
算法
数据结构刷题:第五天
具体地,我们首先遍历该数组一次,如果某个元素为 0,那么就将该元素所在的行和列所对应标记数组的位置置为 true。最后我们再次遍历该数组,用标记数组更新原数组即可。
58 0
数据结构刷题:第五天
|
存储 算法
数据结构刷题:第七天
具体地,我们可以使用哈希表来存储所有已经访问过的节点。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。
70 0
数据结构刷题:第七天
|
存储 算法 JavaScript
数据结构刷题:第六天
在第一次遍历时,我们使用哈希映射统计出字符串中每个字符出现的次数。在第二次遍历时,我们只要遍历到了一个只出现一次的字符,那么就返回它的索引,否则在遍历结束后返回 −1。
86 0
数据结构刷题:第六天
|
机器学习/深度学习 算法
数据结构刷题:第十天
时间复杂度:O(n),其中 nn 为二叉搜索树的节点个数。Morris 遍历中每个节点会被访问两次,因此总时间复杂度为 O(2n)=O(n)。
33 0
数据结构刷题:第十天
|
存储
数据结构刷题:第九天
当我们遇到一个右括号时,我们需要将一个相同类型的左括号闭合。此时,我们可以取出栈顶的左括号并判断它们是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串 s 无效,返回False。为了快速判断括号的类型,我们可以使用哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号。
61 0
数据结构刷题:第九天
|
存储 算法
数据结构刷题:第十二天
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。
53 0
数据结构刷题:第十二天