原题地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/description/
 
给定两个数组,写一个方法来计算它们的交集。

例如:

给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].

注意:

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

跟进:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
  • 如果nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办?

以上是原题

 
我们先按照常规思路解题,再逐步分析最后的集中特殊情况。
 
  思路:
  1、增加一个计数器,用来记录其中一个数组元素出现的次数。
  2、遍历另一个数组,如果该数组元素在计数器中有记录且记录的次数大于1,将该数字新增到结果数组中,同时计数器该数字记录的次数减1。
  实现代码如下:
     public int[] intersect(int[] nums1, int[] nums2) {
Map<Integer, Integer> counter = new HashMap<>(); //计数器,key为数组中的数字,value为该数字在数组中出现的次数
for (int i = 0; i < nums1.length; i++) {
int num = nums1[i];
if (counter.containsKey(num)) {
counter.put(num, counter.get(num) + 1);
} else {
counter.put(num, 1);
}
}
List<Integer> tempList = new ArrayList<>();
for (int i = 0; i < nums2.length; i++) {
int num = nums2[i];
if (counter.containsKey(num) && counter.get(num) > 0) {
counter.put(num, counter.get(num) - 1); //计数器中记录该数字的次数减1
tempList.add(num); //将该数字添加到list中
}
}
int[] result = new int[tempList.size()];
//为满足题目返回值类型,将list转换为int数组
for (int i = 0; i < result.length; i++) {
result[i] = tempList.get(i);
}
return result;
}

  OK,基本功能已经实现,下一步我们一起思考如何满足几个跟进问题:

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

  思路:因为两个数组都是有序的,那我们完全可以用两个指针c1和c2分别顺序扫描两个数组,得到两个数字m和n,有以下三种关系:

  1、m == n,则该数字是重复数字,将该数字添加到结果数组中,同时将两个指针分别后移一位。

  2、m > n,我们需要将c2指针后移一位。

  3、m < n,我们需要将c1指针后移一位。

  重复以上步骤,直到c1或c2其中一个指针已移动到数组末端。

  代码实现如下:

     public int[] intersect(int[] nums1, int[] nums2) {
int cur1 = 0, cur2 = 0; // 定义指针,指向数组开始位置
List<Integer> list = new ArrayList<>();
while (cur1 < nums1.length && cur2 < nums2.length) { // 循环结束条件:任何一个指针指向对应数组的末端
int num1 = nums1[cur1];
int num2 = nums2[cur2];
if (num1 == num2) { // 重复数字,加入结果列表中
list.add(num1);
cur1++;
cur2++;
} else if (num1 < num2) { // 将cur1指针后移一位,继续下一次比较
cur1++;
} else { // 将cur2指针后移一位,继续下一次比较
cur2++;
}
}
int[] result = new int[list.size()];
// 为满足题目返回值类型,将list转换为int数组
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
  我们来对比上述两种方法:
  假设nums1和nums2的长度为l1, l2。
 
  第一种:
    不考虑结尾转换int数组的循环,一共有两处循环:
    1、第一次循环nums1初始化计数器。
    2、第二次循环nums2与计数器中存储的数值作比较。
    无论如何,这两种循环都需要完全执行,实际循环次数为 l1 + l2。
 
  第二种:
    不考虑结尾转换int数组的循环,一共有一处循环:
    1、每次循环同时在nums1和nums2中取值对比,如果相等,同时移动两个指针,一个指针结束后,循环结束。因为 l1 比 l2 小很多,只需要执行完l1次循环即可,实际消耗时间远远小于第一种方法。
 
    最差的情况:最差的情况是nums1和nums2中完全没有一个重复数字,且nums1中的最后一个元素大于nums2的倒数第二个元素,nums2的最后一个元素大于nums1的倒数第二个元素,在这种情况下,第二种方法的循环也同样需要执行 l1 + l2次。
 
  因此,只有在极端情况下,两种方法效率大约相等,其他任何情况下,第二种方法是要优于第一种方法的。
 
  • 如果nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办?

  如果nums2的元素多到无法一次性加载到内存中,那我们应该:

  1、将nums1中的数字初始化计数器。

  2、使用缓冲流读取文件的一部分数据,计数器中有记录且记录的次数大于1,将该数字新增到结果数组中,计数器中该数字记录的次数减1,这样完成了这一部分数据的统计。

  3、接着再读取文件中下一部分数据,重复步骤2。

  

OK,以上是这个问题的一些想法,如果朋友们有更好的方式,欢迎留言交流哈~

  

两个数组的交集 II [ LeetCode - 350 ]的更多相关文章

  1. 【Leetcode】【简单】【350. 两个数组的交集 II】【JavaScript】

    题目描述 350. 两个数组的交集 II 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2]输出: [2,2] 示例 2 ...

  2. 前端与算法 leetcode 350. 两个数组的交集 II

    目录 # 前端与算法 leetcode 350. 两个数组的交集 II 题目描述 概要 提示 解析 解法一:哈希表 解法二:双指针 解法三:暴力法 算法 # 前端与算法 leetcode 350. 两 ...

  3. Java实现 LeetCode 350 两个数组的交集 II(二)

    350. 两个数组的交集 II 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入 ...

  4. LeetCode初级算法之数组:350 两个数组的交集 II

    两个数组的交集 II 题目地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/ 给定两个数组,编写一个函数来计算它们的交 ...

  5. 6、两个数组的交集 II

    6.两个数组的交集 II 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: n ...

  6. leecode刷题(6)-- 两个数组的交集II

    leecode刷题(6)-- 两个数组的交集II 两个数组的交集II 描述: 给定两个数组,编写一个函数来计算它们的交集. 示例: 输入: nums1 = [1,2,2,1], nums2 = [2, ...

  7. LeetCode 350: 两个数组的交集 II Intersection of Two Arrays II

    题目: 给定两个数组,编写一个函数来计算它们的交集. Given two arrays, write a function to compute their intersection. 示例 1: 输 ...

  8. 350 Intersection of Two Arrays II 两个数组的交集 II

    给定两个数组,写一个方法来计算它们的交集.例如:给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].注意:       输出结果中每个元素出现的次数, ...

  9. 【leetcode 简单】 第八十五题 两个数组的交集 II

    给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5 ...

随机推荐

  1. 一笔画问题 南阳acm42(貌似没用到什么算法)

    一笔画问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下 ...

  2. (数据科学学习手札05)Python与R数据读入存出方式的总结与比较

    在数据分析的过程中,外部数据的导入和数据的导出是非常关键的部分,而Python和R在这方面大同小异,且针对不同的包或模块,对应着不同的函数来完成这部分功能: Python 1.TXT文件 导入: 以某 ...

  3. html中显示指数、底数

    在web前端开发中,经常要显示指数.底数,比如x2,loga,我们可以使用span标签,通过控制标签内字体大小,对齐方式来实现想要的效果.代码如下 <table> <tr> & ...

  4. 20145202马超《网络对抗》Exp3免杀 进阶

    木马化正常软件,如通过改变机器指令.实现可免杀免防火墙提示的后门. 继上次实验3所做的代码在主函数里面加上一行调用就可以 改各种属性,这里我参考了郝浩同学的博客 最后我还是遇到了问题 后来发现虽然有那 ...

  5. xssbypass小记

    简单整理下bypass的一些点 标签外 如果是标签之外 又有htmlspecialchars函数的点 就别想了 在标签外同时能xss但是有长度限制 如果是储存型可以利用多个点 然后构造<scri ...

  6. Django学习之天气调查实例(3):部署静态文件CSS、JS、images等(部署环境基于Ubuntu)

    在设计登录界面时,采用了网上下载的登录模板,漂亮,简易.但是在测试和部署时,发现原来模板中采用的js文件和css文件,却着实让我折腾了好几天. 在以往的网页设计中,一般只要把测试站点开启后,网页中的静 ...

  7. 基于Ubuntu Server 16.04 LTS版本安装和部署Django之(一):安装Python3-pip和Django

    近期开始学习基于Linux平台的Django开发,想配置一台可以发布的服务器,经过近一个月的努力,终于掌握了基于Apache和mod-wsgi插件的部署模式,自己也写了一个教程,一是让自己有个记录,二 ...

  8. mutation与vuex区别

    vuex- action   1.当点发送过快,页面中渲染的内容与state中的数据不一致,vuex里面的state变得慢,且不持续更新 2.action中是可以做到页面中state中数据保持一致 责 ...

  9. ExtJs工具篇(3)——Aptana Studio3乱码的问题

            在Aptana Studio里面使用,发现输入的中文是乱码,在浏览器中浏览也是乱码,想着肯定是编码的问题,但是一直没有找到在那个地方设置.以为汉化后就可以了,没想到汉化后竟然还是乱码, ...

  10. 【APUE】Chapter1 UNIX System Overview

    这章内容就是“provides a whirlwind tour of the UNIX System from a programmer's perspective”. 其实在看这章内容的时候,已经 ...