题目:454. 四数相加 II - 力扣(LeetCode)
想法/思路:
方法一:四层for循环不出意外的超时。
方法二:拆分数据量,四个数组两两组合,将其中一组和加入 map 中,另外一组进行到 map 中取值即可,取到则进行++操作。
代码实现:
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
// 四层for循环
int count = 0;
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
for (int k = 0; k < nums3.length; k++) {
for (int l = 0; l < nums4.length; l++) {
int sum = nums1[i] + nums2[j] + nums3[k] + nums4[l];
if (sum == 0) {
count++;
}
}
}
}
}
return count;
}
}
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
// 拆分数据量,四个数组两两组合
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
int mid1 = nums1[i] + nums2[j];
map.put(mid1, map.getOrDefault(mid1, 0) + 1);
}
}
int count = 0;
for (int i = 0; i < nums3.length; i++) {
for (int j = 0; j < nums4.length; j++) {
int mid2 = nums3[i] + nums4[j];
if (map.get(-mid2) != null) {
count += map.get(-mid2);
}
}
}
return count;
}
}
题目:383. 赎金信 - 力扣(LeetCode)
想法/思路:
magazine 中获取字符能否组成 ransomNote,且每个字符只能使用一次。显然可以用 map。
代码实现:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
// magazine中获取字符能否组成ransomNote,且每个字符只能使用一次。
// 显然可以用map
if (ransomNote.length() > magazine.length()) return false;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < magazine.length(); i++) {
char c1 = magazine.charAt(i);
map.put(c1, map.getOrDefault(c1, 0) + 1);
}
for (int i = 0; i < ransomNote.length(); i++) {
char c2 = ransomNote.charAt(i);
if (!map.containsKey(c2)) {
return false;
} else if (map.get(c2) == 1) {
map.remove(c2);
} else {
map.put(c2, map.get(c2) - 1);
}
}
return true;
}
}
题目:15. 三数之和 - 力扣(LeetCode)
想法/思路:
排序、遍历、双指针、去重(三个数分别去重)。 实现细节还差点意思,突然发现找bug的过程就是提升代码理解程度的过程。
代码实现:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
// 简单排个序
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) { // 对第一个数去重
continue;
}
int left = i + 1, right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
ans.add(Arrays.asList(nums[i], nums[left], nums[right]));
left++;
right--;
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
} else if (sum > 0) {
right--;
} else if (sum < 0) {
left++;
}
}
}
return ans;
}
}
题目:18. 四数之和 - 力扣(LeetCode)
想法/思路:
排序、双层遍历、双指针、去重。
注意:
JAVA 中八种数据类型及其数据范围都是多少?
在Java中,有以下八种基本数据类型及其数据范围:
1. byte:1个字节,取值范围为-128到127。计算过程如下:
- 最小值:-2^(8-1) = -2^7 = -128
- 最大值:2^(8-1) - 1 = 2^7 - 1 = 127
2. short:2个字节,取值范围为-32768到32767。计算过程如下:
- 最小值:-2^(16-1) = -2^15 = -32768
- 最大值:2^(16-1) - 1 = 2^15 - 1 = 32767
共计5位数!
3. int:4个字节,取值范围为-2147483648到2147483647。计算过程如下:
- 最小值:-2^(32-1) = -2^31 = -2147483648
- 最大值:2^(32-1) - 1 = 2^31 - 1 = 2147483647
共计10位数!
4. long:8个字节,取值范围为-9223372036854775808到9223372036854775807。计算过程如下:
- 最小值:-2^(64-1) = -2^63 = -9223372036854775808
- 最大值:2^(64-1) - 1 = 2^63 - 1 = 9223372036854775807
共计19位
5. float:4个字节,取值范围为-3.402823e+38到3.402823e+38。计算过程如下:
- 最小值:-1.4e^-45 * 2^127 ≈ -3.402823e+38
- 最大值:(1 - 2^-23) * 2^127 ≈ 3.402823e+38
6. double:8个字节,取值范围为-1.7976931348623157e+308到1.7976931348623157e+308。计算过程如下:
- 最小值:-1.7e^-308 * 2^1023 ≈ -1.7976931348623157e+308
- 最大值:(1 - 2^-52) * 2^1023 ≈ 1.7976931348623157e+308
7. boolean:1个字节,取值范围为true或false。
8. char:2个字节,取值范围为0到65535。计算过程如下:
- 最小值:0
- 最大值:2^16 - 1 = 65535
代码实现:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
for (int j = nums.length - 1; j > i; j--) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
if (j < nums.length - 1 && nums[j] == nums[j + 1]) {
continue;
}
int left = i + 1, right = j - 1;
while (left < right) {
long sum = (long)nums[i] + nums[j] + nums[left] + nums[right]; // 数据范围需要注意一下
if (sum == target) {
ans.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
left++;
right--;
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
} else if (sum > target) {
right--;
} else {
left++;
}
}
}
}
return ans;
}
}