https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/submissions/
解题思路:
1、哈希表
1)一个数组 创建为哈希表, 记录键:元素 值:元素出现的次数
2)另一个数组利用O(1)时间查找,若出现则次数减去1
3)输出新结果放入数组内
//C++
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2)
{
if (nums1.size() > nums2.size())
{
return intersect(nums2, nums1);//交换,数组元素较少的用于创建哈希表
}
unordered_map<int, int> m;
for (auto n : nums1)
{
++m[n];
}
int k = 0;
for (auto n : nums2) {
auto it = m.find(n);//寻找元素对应的迭代器
if (it != end(m) && --it->second >= 0) //value值也即是计数值大于等于0(注意还有等于号,不然出错) https://blog.csdn.net/tcx1992/article/details/80928790
{
nums1[k++] = n;//覆盖nums1没有再用到
}
}
return vector(begin(nums1), begin(nums1) + k);
}
};
注意上述等同于--(it->second)>=0
unordered_map是一个关联容器:
map可以键值是有序的,而 unordered_map键值顺序可变
创建:
unordered_map<int, int> m;表示创建第一个键为int型,第二个值为int型
方法:
begin():指向第一个元素
end():指向最后一个元素之后的位置
find():如果键在map中找不到则返回最后一个元素的下一个位置
it->first指向键 ,it->second指向值
参考:https://www.geeksforgeeks.org/unordered_map-in-cpp-stl/
//Java
class Solution {
public int[] intersect(int[] nums1, int[] nums2)
{
if (nums1.length > nums2.length)
{
return intersect(nums2, nums1);
}
HashMap<Integer, Integer> m = new HashMap<>();
for (int n : nums1)
{
m.put(n, m.getOrDefault(n, 0) + 1);
}
int k = 0;
for (int n : nums2)
{
int cnt = m.getOrDefault(n, 0);
if (cnt > 0)
{
nums1[k++] = n;
m.put(n, cnt - 1);
}
}
return Arrays.copyOfRange(nums1, 0, k);
}
}
HashMap-Java
创建:
HashMap<Integer, Integer> m = new HashMap<>();
键唯一,值可以不唯一
方法:
getOrDefault(Object key, V defaultValue):返回key对应的value值,若找不到则使用默认值defaultValue
Object put(Object key, Object value):插入键值对
Object get(Object key): 检索或获取指定键对应的值
参考:https://www.geeksforgeeks.org/java-util-hashmap-in-java-with-examples/
public static int[] copyOfRange(int[] original_array, int from_index, int to_index):创建原始数据的副本,指向从from_index到to_index
参考:https://www.geeksforgeeks.org/java-util-arrays-copyofrange-java/
算法复杂度分析:
时间复杂度:O(n+m)
空间复杂度:O(min(n,m))
如果给定的数组已经排好序呢?你将如何优化你的算法?
2、使用双指针
//C++
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2)
{
sort(begin(nums1), end(nums1));//排序
sort(begin(nums2), end(nums2));
int i = 0, j = 0, k = 0;
while (i < nums1.size() && j < nums2.size())
{
if (nums1[i] < nums2[j])
{
++i;
} else if (nums1[i] > nums2[j])
{
++j;
} else
{
nums1[k++] = nums1[i++];
++j;
}
}
return vector<int>(begin(nums1), begin(nums1) + k);
}
};
//java
class Solution {
public int[] intersect(int[] nums1, int[] nums2)
{
Arrays.sort(nums1);
Arrays.sort(nums2);
int i = 0, j = 0, k = 0;
while (i < nums1.length && j < nums2.length)
{
if (nums1[i] < nums2[j])
{
++i;
}
else if (nums1[i] > nums2[j])
{
++j;
}
else
{
nums1[k++] = nums1[i++];
++j;
}
}
return Arrays.copyOfRange(nums1, 0, k);
}
}
算法复杂度分析:
时间复杂度:O(n+logn+m+logm) ?排序时间+ while (i < nums1.length && j < nums2.length) 运行的次数
空间复杂度:O(1)