LeetCode 350--两个数组的交集 II --数组--简单

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、使用双指针

1)两个数组先排序
2)定义双指针,分别指向两个数组首位置,若相等则输出,若num1(i)<num2(j) 则i++  否则j++
//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)

发布了136 篇原创文章 · 获赞 112 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/heda3/article/details/104034205