leetcode每日一题 使用golang和java实现 两个数组的交集 哈希图方法和集合方法

两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。
在这里我使用的解体思路是这样的,首先,建立一个集合,将数组一中的数据放入集合,然后遍历数组二,当遇到与集合一中有相用数据的时候,删除集合一中的该数字,然后把该数字放入集合二,当遍历完数组二的时候,集合二中就是所求元素,然后作为返回值输出。

使用哈希图求解

具体思路是这样的:首先我将数组一的数字的值作为key,把出现的次数作为value,这样一来,在向哈希图中建立映射关系的过程中每次出现已经存在映射关系的key时,将它做对应的映射的value+1,这样将数据全部遍历之后,哈希图中所对应的映射关系就是数值与其出现次数的关系。然后遍历数组二,每个数字与哈希图比较,存在且出现次数大于0的时候,将数字添加到目标数组,然后将哈希图中次数-1。当遍历完数组二,便得到所求的目标数组。

使用golang中map实现

func intersect(nums1 []int, nums2 []int) []int {
    keyStore := make(map[int]int)
    for _ , v := range nums1 {
        _ , ok := keyStore[v]
        if  ok {
             keyStore[v] =  keyStore[v] +1 
        }else {
             keyStore[v] = 1 
        }
    }
    r := []int{}
    for _ , v :=  range nums2 {
        if  value, ok := keyStore[v] ; ok {
           if  value -1 >= 0 {
               r = append(r , v)
               keyStore[v] = value -1
           }
        }
    }
    return r 
}

使用java哈希图求解

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map = new HashMap<>(nums1.length);
        for(int num : nums1){
            if(map.containsKey(num)){
                int times = map.get(num);
                times++;
                map.put(num, times);
            }else{
                map.put(num, 1);
            }
        }
        int i = 0;
        List<Integer> list = new ArrayList<>();
        for(int num : nums2){
            if(map.containsKey(num)){
                if(map.get(num) != 0){
                    Integer times = map.get(num);
                    times--;
                    map.put(num, times);
                    list.add(num);
                }
            }
        }
        int[] temp = new int[list.size()];
        for (int num : list) {
            temp[i++] = num;
        }
        return temp;
    }
}

在这里我发现了代码的一种优化方式,这样做可以将运行耗时提高2ms

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map = new HashMap<>(nums1.length);
        // 将 nums1 出现的数值及频次放入映射中
        for (int num : nums1) {
            Integer count = map.get(num);
            if (count == null) {
                map.put(num, 1);
            } else {
                map.put(num, ++count);
            }
        }
        List<Integer> list = new ArrayList<>();
        for (int num : nums2) {
            // 获取映射中该数值出现的频次
            Integer count = map.get(num);
            if (count != null && count != 0) {
                list.add(num);
                // 注意每次匹配后,该数值的频次需要减 1(nums1 和 nums2 匹配的数值的频次要相同)
                map.put(num, --count);
            }
        }
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        return res;
    }
}

哈希图测试结果
虽然在执行用时方面有了一定的提升,但是内存始终还存在一定的问题。

使用java集合实现

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        for(int num : nums1){
           list1.add(num);
        }
        for(int num : nums2){
            if(list1.contains(num)){
                list2.add(num);
                list1.remove(Integer.valueOf(num));
            }
        }
        int[] temp = new int [list2.size()];
        int i = 0;
        for(int num : list2){
            temp[i] =  num;
            i++;
        }
        return temp;
    }
}

这里进行标注一下
list1.remove(Integer.valueOf(num));
这个语句我本以为是删除所有值为num的集合元素,但是这里发现,每次删除其实只是删除了一个。
双集合的测试结果
可见,使用两个集合做交集运算并不是最优解。所以我尝试使用哈希图的数据结构来求解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值