1. Two Sum (Easy) (ALL)

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
Solution 1: Brute Force O(n^2); O(1) 未TLE

这题明显可以用暴力搜索解决:i从0开始遍历,j从i + 1开始遍历,检查nums[i]+nums[j]是否等于target,若等于,返回结果。

    public int[] twoSum(int[] nums, int target) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[]{-1, -1};
    }
Solution 2: HashMap O(n); O(n)

O(n^2)的时间复杂度肯定是不能满足面试官的要求的,所以考虑用空间换时间。
因为要求返回索引,所以我们需要一个数据结构来记录num和其索引,很自然想到用HashMap。
但是我们需要考虑下这里的key是否唯一,因为nums可能存在duplicate。
因为题目说了有且只有一个解S,那么如果nums中有重复数a,有两种情况,

  1. a∉S,这种情况a和S无关,value随便覆盖。
  2. S={a,a},且这种情况下a只能出现两次,当找到第二个a时,S已经确定,不用覆盖第一个a的value。
    不可能有这种情况:S={a,b}, S={a', b},这样的话就有两个解了。所以可以认为key唯一。
    这样解法就清楚了:遍历数组,用HashMap存num和其index,检查map是否存在target-nums[i],若存在,返回结果。
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(target - nums[i])) {
                return new int[]{map.get(target - nums[i]), i};
            }
            map.put(nums[i], i); //这行代码只能放在if下面,先检查,没找到解再存入map。
        }
        return new int[]{-1, -1};
    }
Follow Up:
  1. two sum with duplicates 比如说{1, 2, 2, 3},target = 5, 他要{(2, 3), (2, 3)}
    本质是3sum的简化版,但是要保留重复结果,下面的代码其实不太对,因为会漏一些结果,TODO
    注:如果要返回distinct pairs,那就真正是3Sum的简化版了。
    sort + Two Pointers O(n log n); O(1)

        public static List<List<Integer>> twoSumE(int[] nums, int target) {
            List<List<Integer>> res = new ArrayList<>();
            if (nums == null || nums.length < 2) {
                return res;
            }
    
            Arrays.sort(nums);
            int l = 0;
            int r = nums.length - 1;
            while (l < r) {
                if (nums[l] + nums[r] == target) {
                    res.add(Arrays.asList(nums[l], nums[r]));
    
                    while (l < r && nums[l] == nums[l + 1]) {
                        res.add(Arrays.asList(nums[l], nums[r])); //add duplicate result
                        l++;
                    }
                    while (l < r && nums[r] == nums[r - 1]) {
                        res.add(Arrays.asList(nums[l], nums[r]));  //add duplicate result
                        r--;
                    }
                    l++;
                    r--;
                } else if (nums[l] + nums[r] < target) {
                    l++;
                } else {
                    r--;
                }
            }
            return res;
        }
    
        public static void main(String[] args) {
            int[] nums = {1,2,2,2,3};
            System.out.println(twoSumE(nums, 5));
        }
    
  2. two sum with duplicates, 返回所有的可能的index pairs

        /**
         * duplicate number, 返回所有的可能的index pairs
         * HashMap & HashSet 应该是O(n^2);O(n) 
         * 考虑极端情况,index pair的总数有O(n^2)个[1,1,1,1,1],2
         */
        public List<int[]> twoSumC(int[] nums, int target) {
            if (nums == null) {
                return null;
            }
    
            Map<Integer, Set<Integer>> map = new HashMap<>();
            List<int[]> res = new ArrayList<>();
            for (int i = 0; i < nums.length; i++) {
                if (!map.containsKey(nums[i])) {
                    Set<Integer> set = new HashSet<>();
                    set.add(i);
                    map.put(nums[i], set);
                } else {
                    map.get(nums[i]).add(i);
                }
    
                if (map.containsKey(target - nums[i])) {
                    for (Integer j : map.get(target - nums[i])) {
                        if (j != i) {
                            res.add(new int[]{j, i});
                            System.out.println(j + " " + i);
                        }
                    }
                }
            }
            return res;
        }
    
  3. Input array is sorted, duplicate number, 返回所有的可能的index pairs

    /**
     * Input array is sorted, duplicate number, 返回所有的可能的index pairs
     * Two Pointers O(n);O(1) 下面解法不太对,要改
     * [-1,-1,1,1] 0 result = {(0,2),(0,3),(1,2),(1,3)} 而不是{(0,3),(1,3),(1,2)}
     * set其实也用不到啊,比如你那个例子,已经知道(0,3)这个对了,然后双指针查到-1的个数是2,1的个数是2,
     * 然后写个辅助函数返回0,1和2,3的组合就行
     */
    public List<int[]> twoSumD(int[] nums, int target) {
        if (nums == null) {
            return null;
        }

        int left = 0;
        int right = nums.length - 1;
        List<int[]> res = new ArrayList<>();
        while (left < right) {
            if (nums[left] + nums[right] == target) {
                res.add(new int[]{left, right});
                System.out.println(left + " " + right);
                while (left < right && nums[left] == nums[left + 1]) {
                    left++;
                    res.add(new int[]{left, right});
                }
                while (left < right && nums[right] == nums[right - 1]) {
                    right--;
                    res.add(new int[]{left, right});
                }
            } else if (nums[left] + nums[right] < target) {
                left++;
            } else {
                right--;
            }
        }
        return res;
    }

results matching ""

    No results matching ""