#LeetCode 454. 视频讲解:学透哈希表,map使用有技巧!LeetCode:454.四数相加II_哔哩哔哩_bilibili
解题思路类似Two Sum 题目,区别在于哈希映射的(key, value) 分别代表什么。将a 和b 相加,c 和d 相加后遍历,相比于暴力解决方法的 ,这样的时间复杂度为。类似求两个数的和为0,将a 和b 的和映射在哈希数组中,因为此题不需要去除重复值,所以用value 来保存a + b的和出现的次数,如果遇到- (a + b) 的值出现在(c + d) 中,则出现value 个符合条件的值。
HashMap 的put (key, value) 方法如果遇到key 存在,则将替换旧值为新值。如果key 不存在,将插入新的键值对。HashMap 的getOrDefault(key, default) 可以获取key 键对应的值,如果key 键不存在则返回default 值。
HashMap方法:时间复杂度O().
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
if (nums1.length == 0 || nums2.length == 0 ||
nums3.length == 0 || nums4.length == 0) {
return 0;
}
HashMap sum = new HashMap<>();
int ab = 0, count = 0;
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
int mid_temp = nums1[i] + nums2[j];
sum.put(mid_temp, sum.getOrDefault(mid_temp, 0) + 1);
}
}
for (int i = 0; i < nums3.length; i++) {
for (int j = 0; j < nums4.length; j++) {
int temp = nums3[i] + nums4[j];
count += sum.getOrDefault(-temp, 0);
}
}
return count;
}
}
#LeetCode 383. 文字讲解:代码随想录
类似Anagram题目,用一个哈希数组来记录出现过的字母。如果ransom note 用哈希数组记录,减去magazine 上面的字母,如果哈希数组中依然有> 0 的元素则代表,magazine 上面的字母不能抵消ransom note 的需要,则返回false 。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
if (ransomNote.length() > magazine.length()) {
return false;
}
int[] hash = new int[26];
for (int i = 0; i < ransomNote.length(); i++) {
hash[ransomNote.charAt(i) - 'a']++;
}
for (int j = 0; j < magazine.length(); j++) {
hash[magazine.charAt(j) - 'a']--;
}
for (int k: hash) {
if (k > 0) {
return false;
}
}
return true;
}
}
#LeetCode 15. 视频讲解: 梦破碎的地方!| LeetCode:15.三数之和_哔哩哔哩_bilibili
题目限制:Notice that the solution set must not contain duplicate triplets.
首先使用Arrays.sort() 排序,题目不要求返回下标,所以可以使用排序后的数组完成。方法是:使用双指针遍历,其中一个i 遍历整个数组,作为第一个数字,left 指针指向i 的下一位,作为第二个数字,right 指针指向数组最后一个元素,作为最后一个数字,是在找nums[i] 与那两个数字相加为0 。判断指针移动的标准是三数之和sum 与目标和0 比较,如果sum > 0,则向左移动right 指针(左边的数字小于右边数字),如果sum < 0,则向右移动left 指针,来调整sum ,前提是left < right ,如果left = right 时,则变成了2 数之和,不满足题意。
去除重复:用当前元素与前一个元素比较(因为与前一个元素比较,所以限制i > 0),如果相等则代表已经出现过,则continue 跳过此次循环。在选出三个数值后再对left 指针和right 指针去重,如果left 指针(right 指针)指向的元素与下一个元素相同,那么直接移动到下一个元素,即跳过了相同值,达到去除重复的目的。
双指针方法:
class Solution {
public List> threeSum(int[] nums) {
List> result = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[0] > 0) {
return result;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.length - 1;
int sum;
while (left < right) {
sum = nums[i] + nums[left] + nums[right];
if (sum < 0) {
left++;
}
else if (sum > 0) {
right--;
}
else {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
right--;
left++;
}
}
}
return result;
}
}
#LeetCode 18. 视频讲解: 难在去重和剪枝!| LeetCode:18. 四数之和_哔哩哔哩_bilibili
与四数之和为0 题目的区别,题目要求unique ,则需要去除重复数组。
剪枝操作:如果当前元素大于0 (e.g. [-4, -1, -1, 1] target = -5,如果不限制大于0 ,这个结果会被跳过)且大于目标值target ,则返回当前已经保存的result ,如果第一个元素大于0 且大于目标值target ,则返回空result 。
去重操作:与三个数之和相同。
双指针方法:
class Solution {
public List> fourSum(int[] nums, int target) {
List> result = new ArrayList<>();
Arrays.sort(nums);
for (int k = 0; k < nums.length; k++) {
if (nums[k] > target && nums[k] > 0) {
return result;
}
if (k > 0 && nums[k] == nums[k - 1]) {
continue;
}
for (int i = k + 1; i < nums.length; i++) {
if (i > k + 1 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
long sum = nums[k] + nums[i] + nums[left] + nums[right];
if (sum > target) {
right--;
}
else if (sum < target) {
left++;
}
else {
result.add(Arrays.asList(nums[k],
nums[i], nums[left], nums[right]));
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
left++;
right--;
}
}
}
}
return result;
}
}