在面试同学们的时候,考验编程能力最常问的问题,总的思路是先排序,采用双指针+多层遍历方式,最终时间复杂度是减N。
考核结果:第一层思路清晰,有全局的理解(暴力+双指针)
第二层:手写编程完成暴力
第三层:完成双指针,并给出复杂度解释;最后加分项是给出优化方案;
面向工作1-3年同学,属于必回的题目。
相似的题:两数之和、三数之和、四数之和
public List> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List> ans = new ArrayList<>();
int n = nums.length;
for (int a = 0; a < n - 3; a++) { // 枚举第一个数
long x = nums[a]; // 使用 long 避免溢出
if (a > 0 && x == nums[a - 1]) continue; // 跳过重复数字
if (x + nums[a + 1] + nums[a + 2] + nums[a + 3] > target) break; // 优化一
if (x + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue; // 优化二
for (int b = a + 1; b < n - 2; b++) { // 枚举第二个数
long y = nums[b];
if (b > a + 1 && y == nums[b - 1]) continue; // 跳过重复数字
if (x + y + nums[b + 1] + nums[b + 2] > target) break; // 优化一
if (x + y + nums[n - 2] + nums[n - 1] < target) continue; // 优化二
int c = b + 1, d = n - 1;
while (c < d) { // 双指针枚举第三个数和第四个数
long s = x + y + nums[c] + nums[d]; // 四数之和
if (s > target) d--;
else if (s < target) c++;
else { // s == target
ans.add(List.of((int) x, (int) y, nums[c], nums[d]));
for (c++; c < d && nums[c] == nums[c - 1]; c++) ; // 跳过重复数字
for (d--; d > c && nums[d] == nums[d + 1]; d--) ; // 跳过重复数字
}
}
}
}
return ans;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.fourSum(new int[]{1, 0, -1, 0, -2, 2}, 0));
}
组合总和采用的方案:
是回溯算法+一部分剪枝
-----------------------------------------------------
比较相似的一道题:
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "" 输出:[]
示例 3:
输入:digits = "2" 输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围 ['2', '9']
的一个数字。Related Topics
public static void main(String[] args) {
Solution17 solution = new Solution17();
System.out.println(solution.letterCombinations("2398"));
}
public List letterCombinations(String digits) {
List combinations = new ArrayList();
if (digits.length() == 0) {
return combinations;
}
Map phoneMap = new HashMap() {{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}};
backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
return combinations;
}
public void backtrack(List combinations, Map phoneMap, String digits, int index, StringBuffer combination) {
if (index == digits.length()) {
combinations.add(combination.toString());
} else {
char digit = digits.charAt(index);
String letters = phoneMap.get(digit);
int lettersCount = letters.length();
for (int i = 0; i < lettersCount; i++) {
combination.append(letters.charAt(i));
backtrack(combinations, phoneMap, digits, index + 1, combination);
combination.deleteCharAt(index);
}
}
}
------------------------------------------