zoukankan      html  css  js  c++  java
  • 简单-350-两个数组的交集

    给定两个数组,编写一个函数来计算它们的交集。

    示例 1:

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

    输出: [2,2]
    示例 2:

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

    输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
    我们可以不考虑输出结果的顺序。
    进阶:

    如果给定的数组已经排好序呢?你将如何优化你的算法?

    如果 nums1 的大小比 nums2 小很多,哪种方法更优?

    如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

    需要多次记录交集中的重复元素,倘若无此条件,只需用set即可。考虑到需要记录重复元素的出现次数,可以考虑hashmap;关于空间复杂度,主要考虑哈希表的空间,因此选择长度小的数组取哈希映射,数组值为key,出现次数为value。

    也可以考虑排序数组后,对两个数组迭代,双指针,空间复杂度小。为了节省空间,两种方法都可以将小数组作为目标输出数组,找到交集元素后给小数组从首位开始赋值。

    /*如果 nums1 元素个数大于 nums2,则交换数组元素。
    对于 nums1 的每个元素,添加到 HashMap m 中,如果元素已经存在则增加对应的计数。
    初始化 k = 0,记录当前交集元素个数。
    遍历数组 nums2:
    检查元素在 m 是否存在,若存在且计数为正:
    将元素拷贝到 nums1[k],且 k++。
    减少 m 中对应元素的计数。
    返回 nums1 前 k 个元素。
    时间复杂度:mathcal{O}(n + m)O(n+m)。其中 nn,mm 分别代表了数组的大小。
    空间复杂度:mathcal{O}(min(n, m))O(min(n,m)),我们对较小的数组进行哈希映射使用的空间。
    */
    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);
    }
    /*
    对数组 nums1 和 nums2 排序。
    初始化指针 i,j 和 k 为 0。
    指针 i 指向 nums1,指针 j 指向 nums2:
    如果 nums1[i] < nums2[j],则 i++。
    如果 nums1[i] > nums2[j],则 j++。
    如果 nums1[i] == nums2[j],将元素拷贝到 nums1[k],且 i++,j++,k++。
    返回数组 nums1 前 k 个元素。
    时间复杂度:mathcal{O}(nlog{n} + mlog{m})O(nlogn+mlogm)。其中 nn,mm 分别代表了数组的大小。我们对数组进行了排序然后进行了线性扫描。
    空间复杂度:O(1)O(1),我们忽略存储答案所使用的空间,因为它对算法本身并不重要。
    */
    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);
    }
  • 相关阅读:
    hdu 5007 水题 (2014西安网赛A题)
    hdu 1698 线段树(成段替换 区间求和)
    poj 3468 线段树 成段增减 区间求和
    hdu 2795 公告板 (单点最值)
    UVaLive 6833 Miscalculation (表达式计算)
    UVaLive 6832 Bit String Reordering (模拟)
    CodeForces 124C Prime Permutation (数论+贪心)
    SPOJ BALNUM (数位DP)
    CodeForces 628D Magic Numbers (数位DP)
    POJ 3252 Round Numbers (数位DP)
  • 原文地址:https://www.cnblogs.com/faded828x/p/13122115.html
Copyright © 2011-2022 走看看