uacs2024

导航

leetcode1. 两数之和、15. 三数之和、18. 四数之和

1. 两数之和

注意,这个要返回的是对应数字的下标。

微信截图_20251023214547

 

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;
    }
}

 

 

 

15. 三数之和

注意,这个返回的是具体数字,不能重复,比如[ -1 , 0 , 1 ] 和 [ -1 , 1 , 0 ]就是重复的。

微信截图_20251023215430

以下为无法通过的超时解,每次添加前都查找是否已存在太耗时间了。

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;
    }
}

 

 

 

 

posted on 2025-10-23 22:06  ᶜʸᵃⁿ  阅读(6)  评论(0)    收藏  举报