代码随想录算法训练营第六天-454四数相加II、383赎金信、15三数之和、18四数之和
Kiml Lv5
  • 前言
    状态:454 和 383 可以 AC,15 超时,18 根据 15 做出,还可以进一步优化

  • 更新

1
24.05.24 初始记录

初步题解

454 四数相加 II

题目链接:(https://leetcode.cn/problems/4sum-ii/)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class LE454 {  
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] nums1 = Arrays.stream(scanner.nextLine().split(",")).filter(Objects::nonNull).mapToInt(Integer::parseInt).toArray();
int[] nums2 = Arrays.stream(scanner.nextLine().split(",")).filter(Objects::nonNull).mapToInt(Integer::parseInt).toArray();
int[] nums3 = Arrays.stream(scanner.nextLine().split(",")).filter(Objects::nonNull).mapToInt(Integer::parseInt).toArray();
int[] nums4 = Arrays.stream(scanner.nextLine().split(",")).filter(Objects::nonNull).mapToInt(Integer::parseInt).toArray();
System.out.println(fourSumCount(nums1, nums2, nums3, nums4));
}

// 和昨天的最后一题差不多
public static int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int res = 0;
HashMap<Integer, Integer> map = new HashMap();
for (int k : nums1) {
for (int i : nums2) {
int sum = k + i;
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
}

for (int i : nums3) {
for (int j : nums4) {
res += map.getOrDefault(-i - j, 0);
}
}

return res;
}
}

383 赎金信

题目链接:(https://leetcode.cn/problems/ransom-note/submissions/534463469/)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class LE383 {  
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String ransomNote = scanner.nextLine();
String magazine = scanner.nextLine();
System.out.println(canConstruct(ransomNote, magazine));
}

// 和242一样的思路
public static boolean canConstruct(String ransomNote, String magazine) {
int[] ints = new int[26];
// 遍历存储数量
for (int i = 0; i < magazine.length(); i++) {
ints[magazine.charAt(i) - 97]++;
}
// 遍历扣除数量
for (int i = 0; i < ransomNote.length(); i++) {
ints[ransomNote.charAt(i) - 97]--;
}
for (int i : ints) {
if (i < 0) {
return false;
}
}
return true;
}
}

15 三数之和

题目链接:(https://leetcode.cn/problems/3sum/description/)

暴力解法,但是这样超时了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static List<List<Integer>> threeSum(int[] nums) {  
// 判断是否重复
HashMap<String, List<Integer>> map = new HashMap<>();

for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
list.sort(Integer::compareTo);
map.put(list.stream().map(integer -> integer + "").collect(Collectors.joining(",")), list);
}
}
}
}
List<List<Integer>> list = new ArrayList<>();
for (Map.Entry<String, List<Integer>> stringListEntry : map.entrySet()) {
list.add(stringListEntry.getValue());
}
return list;
}

看了部分解析改用双指针,可以通过,但是比较慢。而且费时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public static List<List<Integer>> threeSum(int[] nums) {  
nums = Arrays.stream(nums).sorted().toArray();
ArrayList<List<Integer>> list = new ArrayList<>();
// 递增序列,前三位和大于0,直接返回
if (nums[0] + nums[1] + nums[2] > 0) {
return list;
}

int i = 0;
int j = i + 1;
int k = nums.length - 1;
while (i < j && j < k) {
System.out.println(i + " " + j + " " + k);
int sum = nums[i] + nums[j] + nums[k];
if (sum == 0) {
list.add(Arrays.asList(nums[i], nums[j], nums[k]));
j++;
} else if (sum < 0) {
j++;
} else {
k--;
}
while (j > i + 1 && j <= nums.length - 1 && nums[j] == nums[j - 1]) {
j++;
}
while (k > j && k != nums.length - 1 && nums[k] == nums[k + 1]) {
k--;
}
if (j >= k) {
i = i + 1;
while (i != 0 && i <= nums.length - 1 && nums[i] == nums[i - 1]) {
i++;
}
j = i + 1;
k = nums.length - 1;
}
}
return list;
}

18 四数之和

题目链接:(https://leetcode.cn/problems/4sum/description/)

看到题目,就觉得是 15 的进阶版,按照上一题的思路写了一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public static List<List<Integer>> fourSum(int[] nums, int target) {  
Arrays.sort(nums);

ArrayList<List<Integer>> list = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (i != 0 && nums[i] == nums[i - 1]) {
continue;
}

for (int j = i + 1; j < nums.length; j++) {
if (j != i + 1 && nums[j] == nums[j - 1]) {
continue;
}

int left = j + 1;
int right = nums.length - 1;
while (left < right) {
long sum = (long) nums[i] + (long) nums[j] + (long) nums[left] + (long) nums[right];
if (sum < target) {
left++;
} else if (sum > target) {
right--;
} else {
list.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
}
}
}
}
return list;
}

看讲解

454 四数相加 II

题目链接/文章讲解/视频讲解:(https://programmercarl.com/0454.四数相加II.html)

383 赎金信

题目链接/文章讲解:(https://programmercarl.com/0383.赎金信.html)

15 三数之和

题目链接/文章讲解/视频讲解:(https://programmercarl.com/0015.三数之和.html)

确实用 for 循环更好理解。题解的思路更加清晰,而且更快。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static List<List<Integer>> threeSum(int[] nums) {  
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
if (nums[i] > 0) {
return result;
}

/**
* 只能是与前一个比较进行去重
*/
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}

int left = i + 1;
int right = nums.length - 1;
while (right > left) {
int sum = nums[i] + nums[left] + nums[right];
if (sum > 0) {
right--;
} else if (sum < 0) {
left++;
} else {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
/**
* 去重逻辑应该放在找到一个三元组之后
* 否则获取不到结果集
*/
while (right > left && nums[right] == nums[right - 1]) {
right--;
}
while (right > left && nums[left] == nums[left + 1]) {
left++;
}

right--;
left++;
}
}
}
return result;
}

18 四数之和

题目链接/文章讲解/视频讲解:(https://programmercarl.com/0018.四数之和.html)

看了解析。加上剪枝操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static List<List<Integer>> fourSum(int[] nums, int target) {  
Arrays.sort(nums);

ArrayList<List<Integer>> list = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
// nums[i] > target 直接返回, 剪枝操作
if (nums[i] > 0 && nums[i] > target) {
return list;
}

for (int j = i + 1; j < nums.length; j++) {
// 二级剪枝
if (nums[i] + nums[j] > 0 && nums[i] + nums[j] > target) {
break;
}

if (j != i + 1 && nums[j] == nums[j - 1]) {
continue;
}

int left = j + 1;
int right = nums.length - 1;
while (left < right) {
long sum = (long) nums[i] + (long) nums[j] + (long) nums[left] + (long) nums[right];
if (sum < target) {
left++;
} else if (sum > target) {
right--;
} else {
list.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
}
}
}
}
return list;
}
 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
访客数 访问量