首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >LeetCode_349. 两个数组的交集

LeetCode_349. 两个数组的交集

作者头像
小小工匠
发布2021-08-17 11:18:21
发布2021-08-17 11:18:21
3270
举报
文章被收录于专栏:小工匠聊架构小工匠聊架构


题目

https://leetcode-cn.com/problems/intersection-of-two-arrays/


分析

幼稚的方法是根据第一个数组 nums1 迭代并检查每个值是否存在在 nums2 内。如果存在将值添加到输出。这样的方法会导O(n×m) 的时间复杂性,其中 n 和 m 是数组的长度。

为了在线性时间内解决这个问题,我们使用集合 set,在 O(1) 时间复杂度实现操作。

其思想是将两个数组转换为集合 set,然后迭代较小的集合检查是否存在在较大集合中。平均情况下,这种方法的时间复杂度为 O(n+m)


Code

方式一 :Set + 数组

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 
 * 
 * @ClassName: Solution
 * 
 * @Description: 给定两个数组,编写一个函数来计算它们的交集。
 * 
 *               输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。
 * @author: Mr.Yang
 * 
 * @date: 2020年2月9日 下午3:39:28
 */
public class Solution {

	public int[] intersection(int[] nums1, int[] nums2) {
		// 保存目标元素的集合
		List<Integer> targetList = new ArrayList<>();

		// set 元素不重复 ,存放数组1
		Set<Integer> set = new TreeSet<>();
		for (int num : nums1) {
			set.add(num);
		}

		// 遍历数组2,判断是数组2中的每个元素是否在数组1中
		// 存在则加入到targetList
		// 同时为了防止数组2有重复的数据,导致targetList重复,所以要移除set中的元素,防止重复
		for (int num2 : nums2) {
			if (set.contains(num2)) {
				targetList.add(num2);
				set.remove(num2);
			}
		}

		// list转数组
		int[] target = new int[targetList.size()];
		for (int i = 0; i < target.length; i++) {
			target[i] = targetList.get(i);
		}
		return target;
	}

	public static void main(String[] args) {
		Solution solution = new Solution();
		int[] target = solution.intersection(new int[] { 1, 2, 2, 1 }, new int[] { 2, 2 });
		for (int i = 0; i < target.length; i++) {
			System.out.println(target[i] + ",");
		}
	}
}

方式二: 两个 set

代码语言:javascript
复制
public int[] intersection3(int[] nums1, int[] nums2) {
		// 数组1 入set
		HashSet<Integer> set1 = new HashSet<Integer>();
		for (Integer n : nums1) {
			set1.add(n);
		}
		// 数组2 入set
		HashSet<Integer> set2 = new HashSet<Integer>();
		for (Integer n : nums2) {
			set2.add(n);
		}

		// 比较
		if (set1.size() < set2.size()) {
			return setIntersection(set1, set2);
		} else {
			return setIntersection(set2, set1);
		}
	}

	/**
	 * 
	 * 
	 * @Title: setIntersection
	 * 
	 * @Description: 迭代较小的集合检查是否存在在较大集合中 减少遍历次数
	 * 
	 * @param smallSet
	 * @param largeSet
	 * 
	 * @return: int[]
	 */
	private int[] setIntersection(HashSet<Integer> smallSet, HashSet<Integer> largeSet) {
		int[] target = new int[smallSet.size()]; // 先开辟一个小的内存区域
		int idx = 0;// 下面的这种遍历,没有下标,定义一个索引下标
		for (int num : smallSet) {// 迭代较小的集合检查是否存在在较大集合中 减少遍历次数
			if (largeSet.contains(num)) {
				// target[idx] = num;
				// idx++;
				// 上面两行可以直接写成如下
				target[idx++] = num;
			}
		}
		return Arrays.copyOf(target, idx); // 返回idx长度的数组,避免出现多余的0
	}

复杂度分析

  • 时间复杂度:O(m+n),其中 n 和 m 是数组的长度。 O(n) 的时间用于转换 nums1 在集合中, O(m) 的时间用于转换 nums2 到集合中,并且平均情况下,集合的操作为 O(1)
  • 空间复杂度:O(m+n),最坏的情况是数组中的所有元素都不同。

方式三: 内置函数

内置的函数在一般情况下的时间复杂度是 O(n+m) 且时间复杂度最坏的情况是 O(n×m) ,在 Java 提供了 retainAll() 函数.

代码语言:javascript
复制
public int[] intersection(int[] nums1, int[] nums2) {
		// 数组1 入set
		HashSet<Integer> set1 = new HashSet<Integer>();
		for (Integer n : nums1)
			set1.add(n);
		// 数组2 入set
		HashSet<Integer> set2 = new HashSet<Integer>();
		for (Integer n : nums2)
			set2.add(n);

		// 内置函数
		set1.retainAll(set2);

		// set转数组
		int[] output = new int[set1.size()];
		int idx = 0;
		for (int s : set1)
			output[idx++] = s;
		return output;
	}

复杂度分析

  • 时间复杂度:一般情况下是 O(m+n),最坏情况下是 O(m×n)
  • 空间复杂度:最坏的情况是 O(m+n),当数组中的元素全部不一样时。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/02/09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目
  • 分析
  • Code
    • 方式一 :Set + 数组
    • 方式二: 两个 set
    • 方式三: 内置函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档