💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
:-: 1.9 两个数组的交集 ***** **题干** 给定两个数组,编写一个函数来计算它们的交集。 示例 1: ``` 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2] ``` 示例 2: ``` 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出: [9,4] ``` 说明: ``` 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。 ``` **题目分析:** 一看求交集且结果元素不重复,就想到了Set集合无重复值的特性,也可使用其他集合,手动控制不重复。 **新手有可能遇到的解题思路陷阱:** 注意结果集中元素不重复也不允许有其他数组默认值。 **解题思路分析以及代码实现:** 第一种思路:双重嵌套循环+Set集合。 第一种思路代码: ``` public int[] intersection(int[] nums1, int[] nums2) { Set<Integer> set = new HashSet<Integer>(); for (int i = 0; i < nums1.length; i++) { for (int j = 0; j < nums2.length; j++) { if (nums1[i] == nums2[j]) { //元素相等就加入,Set处理重复值 set.add(nums1[i]); break; } } } int[] nums = new int[set.size()]; int i = 0; for (int n : set) { nums[i] = n; i++; } return nums; } ``` 第一种思路:双重嵌套循环+其他集合手动处理重复值。 ``` public int[] intersection(int[] nums1, int[] nums2) { ArrayList<Integer> tmp = new ArrayList<>(); for (int i = 0; i < nums1.length; i++) { //利用indexOf()或者contains()方法判断是否重复 for (int j = 0; j < nums2.length; j++) { if (nums1[i] == nums2[j] && tmp.indexOf(nums1[i]) < 0) { tmp.add(nums1[i]); } } } int[] result = new int[tmp.size()]; for (int i = 0; i < tmp.size(); i++) { result[i] = tmp.get(i); } return result; } ``` ``` public int[] intersection(int[] nums1, int[] nums2) { HashSet<Integer> result_set = new HashSet(); for (int num1 : nums1) { for (int num2 : nums2) { if (num1 == num2) result_set.add(num1); } } //将Set集合转化为数组,简化遍历Set集合的时间 Integer[] result_ = result_set.toArray(new Integer[result_set.size()]); int[] result = new int[result_.length]; for (int i = 0; i < result_.length; i++) { result[i] = result_[i]; } return result; } ``` **复杂度分析** 时间复杂度:O(n^2)。 空间复杂度:O(n)。 第二种思路:排序法。 第二种思路代码: ``` public int[] intersection(int[] nums1, int[] nums2) { Arrays.sort(nums1); Arrays.sort(nums2); ArrayList result = new ArrayList(); int mark = 0; for (int i = 0, j = 0; i < nums1.length && j < nums2.length;) { if (nums1[i] == nums2[j]) { //因为已经经过排序,只需验证前一个与当前是否相同即可 if (result.size() == 0 || nums1[i] != mark) { result.add(nums1[i]); mark = nums1[i]; } i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } int[] res = new int[result.size()]; for (int i = 0; i < result.size(); i++) { res[i] = (int) result.get(i); } return res; } ``` **复杂度分析** 时间复杂度:O(n)。 空间复杂度:O(n)。 第三种思路:利用Java集合自带方法。 为什么将int类型数组转化为Integer类型数组?[Arrays.asList()方法使用](http://blog.sina.com.cn/s/blog_6a6badc90101550l.html) Java集合的求交集,差集方法:[Java集合的求交集,差集方法](https://blog.csdn.net/difffate/article/details/72540220) 第三种思路代码: ``` public int[] intersection(int[] nums1, int[] nums2) { int sizenums1 = nums1.length; int sizenums2 = nums2.length; Integer[] nums12 = new Integer[sizenums1]; Integer[] nums22 = new Integer[sizenums2]; for (int i = 0; i < sizenums1; i++) { nums12[i] = new Integer(nums1[i]); } for (int i = 0; i < sizenums2; i++) { nums22[i] = new Integer(nums2[i]); } Set<Integer> copy = new HashSet<Integer>(); copy.addAll(Arrays.asList(nums12)); copy.retainAll(Arrays.asList(nums22)); int[] ans = new int[copy.size()]; int i = 0; for (int num : copy) { ans[i++] = num; } return ans; } ``` **复杂度分析** 时间复杂度:O(n)。 空间复杂度:O(n)。 第四种思路:空间换时间,双集合。 第四种思路代码: ``` public int[] intersection(int[] nums1, int[] nums2) { Set<Integer> result = new HashSet<>(); Set<Integer> set = new HashSet<>(); // 先将num1全放sets里 for (int i = 0; i < nums1.length; i++) { set.add(nums1[i]);// 放入时候去掉重复的 } for (int j = 0; j < nums2.length; j++) { if (set.contains(nums2[j])) { result.add(nums2[j]);// 放入交集 } } int[] arr = new int[result.size()]; Object[] a = result.toArray(); for (int i = 0; i < a.length; i++) { arr[i] = (int) a[i]; } return arr; } ``` **复杂度分析** 时间复杂度:O(n)。 空间复杂度:O(n)。 第五种思路:排序后查找。 第五种思路代码: ``` public int[] intersection(int[] nums1, int[] nums2) { Set<Integer> set = new HashSet<>(); Arrays.sort(nums1); for (int i = 0; i <= nums2.length - 1; i++) { int top = 0; int bottom = nums1.length - 1; while (top <= bottom) { int mid = top + (bottom - top) / 2; if (nums1[mid] == nums2[i]) { set.add(nums1[mid]); break; } if (nums1[mid] < nums2[i]) { top = mid + 1; } else { bottom = mid - 1; } } } int[] result = new int[set.size()]; int i = 0; for (int num : set) { result[i] = num; i++; } return result; } ``` **复杂度分析** 时间复杂度:O(n * logn)。 空间复杂度:O(n)。 第六种思路:标记法。不使用集合,只使用数组,大大减少了时间。 第六种思路代码: ``` public int[] intersection(int[] nums1, int[] nums2) { int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; // 求出数组nums1中最大值 与最小值 for (int i = 0; i < nums1.length; i++) { max = max < nums1[i] ? nums1[i] : max; min = min > nums1[i] ? nums1[i] : min; } // 标记 boolean[] booleanArray = new boolean[max - min + 1]; for (int i = 0; i < nums1.length; i++) { booleanArray[nums1[i] - min] = true; //去重并加标记 } int index = 0; int[] tempArray = new int[nums2.length]; for (int i = 0; i < nums2.length; i++) { // 找出nums2中的元素,标记改为false if (!(nums2[i] < min) && !(nums2[i] > max) && booleanArray[nums2[i] - min]) { booleanArray[nums2[i] - min] = false; //去重 // 找出相同的数据 tempArray[index++] = nums2[i]; } } // 复制有数值位,舍弃默认数值位 return Arrays.copyOf(tempArray, index); } ``` **复杂度分析** 时间复杂度:O(n)。 空间复杂度:O(n)。 **若有理解错误的、写错的地方、更好的思路,方法,望各位读者评论或者发邮件指正或指点我,不胜感激。**