第七天:哈希表part02
LC454四数相加II(未掌握)
- 未掌握分析:考虑到了四层for循环的暴力解法,甚至很接近正解想到拆分为两组,但是没有继续下去
- 解题思路:四层for循环会超时,分为两组,分别为a+b和c+d,只需要a+b+c+d=0即可,时间复杂度降为O(n^2),并采用hashMap来提升查找效率
- 代码:
LC383赎金信
LC15三数之和(未掌握)
- 未掌握分析:
- 采用确定一个元素,然后找两数之和等于-nums[i]的方法,但是问题在于去重
- i的去重很好处理,直接if(i>0 && nums[i-1]==nums[i]) continue;
- j的去重不好处理,如果是if(j>i+1 && nums[j-1]==nums[j]) continue;
- 测试用例为[-2,0,1,1]时,i=0,j=3时,因为nums[2]==nums[3],会导致错过[-2,1,1]的结果
- 并且已经是第三次看到这个题目了,仍然未想起双指针的想法,警醒!!!
- 错误代码:
- 正确思路:使用双指针来处理,但是数组需要进行排序
- 确定nums[i],定义双指针left和right,其中left = i+1,right = nums.length-1;
- 当nums[i]+nums[left]+nums[right]>0,说明和大了,又因为数组是排序好的,因此right–
- 当nums[i]+nums[left]+nums[right]<0,说明和小了,又因为数组是排序好的,因此left++
- 剪枝操作:当nums[i]>0时,由于数据是排序的,后续的两数之后不可能会小于0,直接return result;
- 去重操作:
- i的去重:if(i>0 && nums[i-1]==nums[i]) continue;
- left和right的去重:
- while(left<right && nums[left]==nums[left+1]) left++;
- while(left<right && nums[right]==nums[right-1]) right–;
- 代码:
LC18四数之和(未掌握)
- 解题思路:
- 思想跟三数之和差不多,只不过是使用了两层for循环,然后使用双指针
- 剪枝操作:
- 三数之和:当nums[i]>0时,由于数据是排序的,后续的两数之后不可能会小于0,直接return result;
- 四数之和:
- 三数之和中0是确定值,因此可使用上诉的剪枝操作,但是因为四数之和中target是不确定的,可能是负数,因此不能使用nums[i]>target。如target=-5,nums=[-4,-1,0,0]则会出错。
- nums[i]>target && target>0
- 因为数据中存在超过int类型界限的数,所以sum要使用long类型,但是
- 切记是long sum = (long)nums[i]+nums[j]+nums[left]+nums[right];
- 而不是long sum = (long)(nums[i]+nums[j]+nums[left]+nums[right]);
- 因为一个超出int界限就可以转换了,接下来的会自动转换,但是四个加起来已经超过了int界限就变成了其他的值再转换,失真了
- 代码: