力扣第一题-两数之和这题第一反应就是hash吗,遍历数组然后看hash[ target-nums[ i ] ]存不存在,曾经我都是用c来写hash的,直接散列在数组上就可以了,随着现在的数据上限越来越大,甚至还有负数就不能用数组了,直接java里一个hashMap就可以搞定。 代码没什么难点,可以分成遍历一次和遍历两次的情况。 一次遍历的话是每一次先找有没有hash[ target-nums[ i ] ],没有的话就把自己存表,这样会在x+y=target的哪个y找到结果。 两次遍历的话第一遍只存入hash表,第二次会在x哪里找到。 时间复杂度的话,第一种是2y,第二种是n+x。差不多。
然后我在想看看最快的java代码的时候发现他是用数组做的,如下:
class Solution { public int[] twoSum(int[] nums, int target) { int volume = 2<<10; //2的10次方 int bitNum = volume-1; //11111111111 int[] res = new int[volume]; for(int i=0;i<nums.length;i++){ int c = (target-nums[i])&bitNum; if(res[c]!=0){ return new int[]{res[c]-1,i}; } res[nums[i]&bitNum] = i+1; } throw new IllegalArgumentException("No two sum solution"); } }开始我一下子被这种没见过的写法惊住了,想了好久int c = (target-nums[i])&bitNum;是为了什么,再加上我隐约有感觉是不是可以把二进制的1111变成10进制的1111这样就可以把符号位给去掉,我就一直在想作者是不是在做这样的尝试,然后我终于发现这个按位与的操作只有一个作用!!! 那就是:把target-nums[i]的前21位给置0,所以-4和4所的的int c都是一样的,只是测试用例太少才没有报错,真的是太马叉虫了。 至于2进制的1111转10进制的1111现在想想真是太蠢了。 我有时候老是回想有没有一些奇怪的方法,但是深感自己基础分析逻辑的缺乏,甚至连思路的线头都不能拿住,忘了分析的轨迹或者形不成连贯的思维。