leetcode 两数之和--比哈希快的方法

leetcode 两数之和--比哈希快的方法

题目原题

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

哈希解法 3ms

一般网路上看的哈希解法是,也是相当快了

    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (map.containsKey(complement)) {
                return new int[] { map.get(complement), i };
            }
            map.put(nums[i], i);
        }
        return null;
        }

目前leetcode 1ms解法

但leetcode神奇之处就是会不断追求极致,目前Java 1ms上的范例是

    public int[] twoSum(int[] nums, int target) {
        
        int indexMax = 0xfff;
        int[] array = new int[indexMax + 1];
        for (int i = 0; i < nums.length; i++) {
            int diff = (target - nums[i]) & indexMax;
            if (array[diff] != 0) {
                return new int[]{array[diff] - 1,i};
            }
            
            array[nums[i] & indexMax] = i+1;
        }
        
        return null;
        }
    }

看到了神奇数字 0xfff,这时就估计是根据测试范例做的硬编码。

把测试数据改为

  		int[] nums= new int [100000];
        for (int i = 0;i<100000;i++){
            nums[i]=i;
        }
        System.out.println(Arrays.toString(twoSum(nums, 99999)));

跑出来的答案是错误的[847, 848]

优化 1ms解法

在百思不得其解后,刷了微信小程序 算法面试 看到有更优解

public int[] twoSum(int[] nums, int target) {
        
        final int i1 =nums.length;
        int il2 =(i1 >> 2) -1;
        
        int pot =2 ;
        
        while((il2 >>=1) > 0 ){
            pot <<= 1;
        }
        final int bitMod =pot -1;
        final int[] bucket =new int[pot];
        final int[] linked =new int[i1];
        
        final int firstVal = nums[0];
        
        
        for (int i=1 ; i<i1 ;i++){
            int currNum = nums[i];
            int complement = target -currNum;
            
            if (complement == firstVal){
                return new int[] {0 ,i};
            }
            
            int complementLLIndex = bucket[complement & bitMod];
            while(complementLLIndex != 0){
                if(nums[complementLLIndex] == complement){
                    //Found
                    return new int[] {complementLLIndex,i};
                }
                complementLLIndex =linked[complementLLIndex];
            }
            int  currNumLLIndex = currNum & bitMod;
            linked[i] = bucket[currNumLLIndex];
            bucket[currNumLLIndex] = i;
                
            }
        
        return null;
        }

答案则是[49999, 50000] , 不过比较复杂 , 在这抛砖引玉,希望大神能做优化~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值