leetcode1. 两数之和、15. 三数之和、18. 四数之和
注意,这个要返回的是对应数字的下标。

2022/09的C++代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int size=nums.size();
unordered_map<int,int> mapmap;
for(int i=0;i<size;i++){
auto it=mapmap.find(target-nums[i]);
if(it == mapmap.end()){
mapmap[nums[i]]=i;
//mapmap.insert(pair<int, int>(nums[i], i));//另一种添加方法
}
else{
return {it->second,i};
}
}
return {};
}
};
2025/10的Java代码
class Solution {
public int[] twoSum(int[] nums, int target) {
int n = nums.length;
int[] res = new int[2];
HashMap<Integer,Integer> record = new HashMap<>();
for(int i = 0;i < n;++i){
if(record.containsKey(nums[i]) && nums[i] * 2 == target){
res[0] = record.get(nums[i]);res[1] = i;
return res;
}
int minus = target - nums[i];
if(record.containsKey(minus) && i != record.get(minus)){//保证不是同一个元素用两次
res[0] = i;res[1] = record.get(minus);
return res;
}
record.put(nums[i],i);
}
return res;
}
}
注意,这个返回的是具体数字,不能重复,比如[ -1 , 0 , 1 ] 和 [ -1 , 1 , 0 ]就是重复的。

以下为无法通过的超时解,每次添加前都查找是否已存在太耗时间了。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
Arrays.sort(nums);
for(int i = 0;i < n;++i){
if(nums[i] > 0) break;
if(i != 0 && nums[i] == nums[i-1]) continue;
HashMap<Integer,Integer> record = new HashMap<>();//记录本轮目标值为(0-nums[i])的哈希表
int target1 = 0 - nums[i];
for(int j = i + 1;j < n;++j){
if(record.containsKey(nums[j]) && nums[j] * 2 == target1){
List<Integer> thisRes = new ArrayList<>(Arrays.asList(nums[i],nums[j],nums[j]));
if(!res.contains(thisRes)) res.add(thisRes);
continue;
}
int target2 = target1 - nums[j];
if(record.containsKey(target2) && j != record.get(target2)){
List<Integer> thisRes = new ArrayList<>(Arrays.asList(nums[i],nums[record.get(target2)],nums[j]));
//res.add(new ArrayList<>(Arrays.asList(nums[i],nums[record.get(target2)],nums[j])));
if(!res.contains(thisRes)) res.add(thisRes);
continue;
}
record.put(nums[j],j);
}
}
return res;
}
}
以上代码改成HashSet,最后再转为List返回就可以通过。保证添加到HashSet时ArrayList是有序的。
但还是太低效。用时417ms,击败5.01%,内存52.50MB,击败5.00%。
法一:哈希集合去重
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
HashSet<List<Integer>> resSet = new HashSet<>();
int n = nums.length;
Arrays.sort(nums);
for(int i = 0;i < n;++i){
if(nums[i] > 0) break;
if(i != 0 && nums[i] == nums[i-1]) continue;
HashMap<Integer,Integer> record = new HashMap<>();//记录本轮目标值为(0-nums[i])的哈希表
int target1 = 0 - nums[i];
for(int j = i + 1;j < n;++j){
if(record.containsKey(nums[j]) && nums[j] * 2 == target1){
resSet.add(new ArrayList<>(Arrays.asList(nums[i],nums[j],nums[j])));
continue;
}
int target2 = target1 - nums[j];
if(record.containsKey(target2) && j != record.get(target2)){
resSet.add(new ArrayList<>(Arrays.asList(nums[i],nums[record.get(target2)],nums[j])));
continue;
}
record.put(nums[j],j);
}
}
return new ArrayList<>(resSet);
}
}
面试官更期望看到的是通过逻辑控制在添加结果之前就避免产生重复三元组,而不是事后用集合过滤。
法二:双指针
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
Arrays.sort(nums);
for (int i = 0; i < n - 2; i++) {
if (nums[i] > 0) break;//如果第一个数已经大于0,后面不可能有解
if (i > 0 && nums[i] == nums[i - 1]) continue; //正确的i去重:与前一个元素比较
int target = -nums[i];
int left = i + 1, right = n - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum < target) left++;
else if (sum > target) right--;
else {
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 在找到三元组后才对j和k去重,防止漏掉[-10,0,1,2,5,5]这样的情况。
// 而且去重的是已经选择的数,而不是未判断的数
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;right--;
}
}
}
return res;
}
}
浙公网安备 33010602011771号