关于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的代码:

<span style="font-size:14px;">    public int[] intersection(int[] nums1, int[] nums2) {
        HashSet intersectSet = new HashSet();
        for(int i=0;i<nums1.length;i++){
            Integer temp = Integer.valueOf(nums1[i]);
            if(!intersectSet.contains(temp)){
                intersectSet.add(temp);
            }
        }
        ArrayList<Integer> result = new ArrayList<Integer>();
        for(int j=0;j<nums2.length;j++){
            Integer temp2 = Integer.valueOf(nums2[j]);
            if(intersectSet.contains(temp2)){
                result.add(temp2);
                intersectSet.remove(temp2);
            }
        }
        int[] finalResult = new int[result.size()];
        for (int k=0;k<result.size();k++){
            finalResult[k] = result.get(k).intValue();
        }
        return finalResult;
    }</span>
首先声明一个HashSet类型的对象intersectSet,然后先把数组nums1转化为集合intersectSet。根据intersectSet中已有的元素,判断nums2中有哪些元素是nums1的交集,并将这些元素add进一个ArrayList类型的对象中,然后将intersectSet中的该元素删除(防止以后的循环中出现相同元素然后重复add到ArrayList这种情况)。最后就是将ArrayList转化为int型数组返回即可。真的是炒鸡容易想到的思路呢。

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

</pre><pre style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 9.5px; margin-top: 0px; margin-bottom: 10px; line-height: 1.42857; word-break: break-all; word-wrap: break-word; color: rgb(51, 51, 51); border: 1px solid rgb(204, 204, 204); border-radius: 0px; max-height: 600px; background-color: rgb(245, 245, 245);"><code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 0px; color: inherit; border-radius: 0px; word-wrap: normal; min-width: 100%; background-color: transparent;"><span style="font-size:14px;">public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<>();
        Set<Integer> 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;
    }</span></code>
第二种是通过先将两个数组进行排序,然后通过比较元素大小的方法确定该元素是不是交集的一部分,如果是的话就添加到一个HashSet的对象中(这里就算相同元素多次add到HashSet中也没关系,HashSet满足集合的基本性质,add多少次相同元素,HashSet中也只会保留一个的)。最后,将HashSet转化为int类型数组即可,代码如下:

<span style="font-size:14px;">public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> 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;
    }</span>

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

<span style="font-size:14px;">    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> 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;
    }</span>
   总结一下,遇到这类“查找数据中相同部分”的问题,使用各种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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值