吐槽
今天好冷哇哇哇,真的是冻死人了,今天看猫猫老睡在那里,然后我过去就舔我的手和脸emmmm。
题目
两数之和给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
思路
这道题还是那种看起来很简单很简单的题目
是个人都能想到两层循环什么的,直接求出来
比如我写的第一版的代码
public int[] twoSum(int[] nums, int target) {
if (nums.length < 2){
return null;
}
int [] result = new int[2];
for (int i = 0;i < nums.length;i++){
for (int j = i+1;j < nums.length;j++){
if ((nums[i] + nums[j]) == target){
result[0] = i;
result[1] = j;
break;
}
}
}
return result;
}
时间大概就是跑完样例50ms 尴尬了
所以说,以后遇到这种简单的题目的话,两层循环什么的肯定先要最后考虑,实在不行再考虑用两层循环
这道题就是简单的在数组中找到两个数子加起来就可以等于目标值
如何减少一层循环呢
用Map
//java的方便之处,感觉有点取巧了
思路也很简单
- 把数值作为 key,它的下标作为 value
- 遍历数组,判断 map 是否含有这个目标值-当前数值,
- 有直接返回,没有的话放到map里面
代码如下,测试用例的时间是5ms
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0 ; i < nums.length;i++){
if (map.containsKey(target - nums[i])){
return new int []{map.get(target - nums[i]),i};
}
map.put(nums[i],i);
}
return new int[]{0,0};
}
然后我好奇看了下这道题2ms的解答算法,简直是自己完全看不懂啊啊啊啊,好像和我都是用的是java啊,,,很尴尬唉
public int[] twoSum(int[] nums, int target) {
final int il = nums.length;
int il2 = (il >> 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[il];
final int firstVal = nums[0];
for (int i = 1; i < il; 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;
}
总结
- 刷题时候一般避免用多重循环什么的
- 如果非要用的话,可以用map代替一层循环//java刷题