关于LeetCode中Intersection of Two Arrays一题的理解

题目如下:

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2].

Note:

  • Each element in the result must be unique.
  • The result can be in any order.
    给定两个int类型的数组,要求返回一个新数组,这个新数组中的元素应该是两个给定数组的交集,由于我们知道集合有三个性质,“无序性”,“互异性”,“确定性”,所以说其实java中的数组并不应该算作严格按照定义而言的集合,因为java中的数组的元素是有顺序的,而且是可以重复的。所以,如果把题干例子中给定的nums1转化为集合的话,应该是{1,2},nums2转换给集合后应该是,{2}。所以,nums1和nums2的交集应该是集合{2}。最终应该返回一个只包含一个元素2的int类型数组。那既然已经提到和集合有关,需要利用到集合的一些性质,所以我们基本的思路就是使用HashSet来进行相关的处理,想到使用HashSet后,逻辑应该就比较清晰了,这里就不赘述了。照例放上本人第一次Accepted的代码:

    public int[] intersection(int[] nums1, int[] nums2) {
        HashSet intersectSet = new HashSet();
        for(int i=0;i result = new ArrayList();
        for(int j=0;j
首先声明一个HashSet类型的对象intersectSet,然后先把数组nums1转化为集合intersectSet。根据intersectSet中已有的元素,判断nums2中有哪些元素是nums1的交集,并将这些元素add进一个ArrayList类型的对象中,然后将intersectSet中的该元素删除(防止以后的循环中出现相同元素然后重复add到ArrayList这种情况)。最后就是将ArrayList转化为int型数组返回即可。真的是炒鸡容易想到的思路呢。

然后是LeetCode讨论区大神的各种套路,第一种和我的方法思路一样,写法也差不多,这里就不再多进行解释了,代码如下:

public int[] intersection(int[] nums1, int[] nums2) {
        Set set = new HashSet<>();
        Set intersect = new HashSet<>();
        for (int i = 0; i < nums1.length; i++) {
            set.add(nums1[i]);
        }
        for (int i = 0; i < nums2.length; i++) {
            if (set.contains(nums2[i])) {
                intersect.add(nums2[i]);
            }
        }
        int[] result = new int[intersect.size()];
        int i = 0;
        for (Integer num : intersect) {
            result[i++] = num;
        }
        return result;
    }
第二种是通过先将两个数组进行排序,然后通过比较元素大小的方法确定该元素是不是交集的一部分,如果是的话就添加到一个HashSet的对象中(这里就算相同元素多次add到HashSet中也没关系,HashSet满足集合的基本性质,add多少次相同元素,HashSet中也只会保留一个的)。最后,将HashSet转化为int类型数组即可,代码如下:

public int[] intersection(int[] nums1, int[] nums2) {
        Set set = new HashSet<>();
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int i = 0;
        int j = 0;
        while (i < nums1.length && j < nums2.length) {
            if (nums1[i] < nums2[j]) {
                i++;
            } else if (nums1[i] > nums2[j]) {
                j++;
            } else {
                set.add(nums1[i]);
                i++;
                j++;
            }
        }
        int[] result = new int[set.size()];
        int k = 0;
        for (Integer num : set) {
            result[k++] = num;
        }
        return result;
    }

第三种是使用二分查找的方法,先讲给定数组其中之一进行排序(这里以nums2为例),然后查找nums1中的每一个元素是否在nums2中,由于nums2是已经排好顺序的,所以我们可以使用“二分法”来提高查找的效率,代码如下:

    public int[] intersection(int[] nums1, int[] nums2) {
        Set set = new HashSet<>();
        Arrays.sort(nums2);
        for (Integer num : nums1) {
            if (binarySearch(nums2, num)) {
                set.add(num);
            }
        }
        int i = 0;
        int[] result = new int[set.size()];
        for (Integer num : set) {
            result[i++] = num;
        }
        return result;
    }
    
    public boolean binarySearch(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (nums[mid] == target) {
                return true;
            }
            if (nums[mid] > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return false;
    }
   总结一下,遇到这类“查找数据中相同部分”的问题,使用各种Hash类型的对象往往是最便捷的方式,时间复杂度更小。上述三种讨论区方法时间复杂度分别为O(n),O(nlogn),O(nlogn)。为什么后两种是时间复杂度都是O(nlogn)呢,因为它们都用到了排序算法,即Arrays.sort()方法,而又由于Arrays.sort()是使用归并排序实现的,所以时间复杂度是O(nlogn)。

   归并排序详情:https://zh.wikipedia.org/wiki/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F


你可能感兴趣的:(java)