Leetcode - Two Sum

Question:

Paste_Image.png

My code:

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        if (nums == null || nums.length == 0)
            return null;
        int[] result = new int[2];
        boolean isOver = false;
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] + nums[j] == target) {
                    result[0] = i + 1;
                    result[1] = j + 1;
                    isOver = true;
                    break;
                }
            }
            if (isOver)
                break;
        }
        
        return result;
    }
}

My test result:

Paste_Image.png

这道题目终于是花了几分钟写出来的。但是复杂度的确是 quadratic的。
后来看了别人的解题思路,觉得的确别人的更加快,只要 o(n).
他的做法就是设置一个hashmap, 存放键值对。
key -> 要得到target所需要的另外一个加数。
value -> 该加数所对应的index
然后对数组进行遍历。每碰到一个新的加数时,查找哈希表,看看其是否已经存在于该表中,即,其是否已被其他数所需要。如果已经存在了,说明有个数可以和他加起来达到目的。然后将它们返回。如果不存在,则将 target - 该加数 的值存入哈希表中,对应的value是 其 index (i + 1).
这就是这道题目的思路。
这是那人的代码:

public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> tracker = new HashMap<Integer, Integer>();
        int len = nums.length;
        for(int i = 0; i < len; i++){
            if(tracker.containsKey(nums[i])){
                int left = tracker.get(nums[i]);
                return new int[]{left+1, i+1};
            }else{
                tracker.put(target - nums[i], i);
            }
        }
        return new int[2];
    }

**
总结:有个疑问, HashMap 和 HashSet到底有什么区别呢?

解答: HashMap -> 添加元素时,添加的 key-value
HashSet -> 添加元素时,添加的value 他的key默认为 数组的index。算是更加简化的HashMap

**

Anyway, Good luck, Richardo!

import java.util.Arrays;
import java.util.HashMap;

public class Solution {
    /* Solution 1. O(n^2)
    public int[] twoSum(int[] nums, int target) {
        if (nums == null || nums.length == 0)
            return null;
        HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; i++)
            hm.put(nums[i], i);
        int[] constant = Arrays.copyOf(nums, nums.length);
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                int sum = nums[i] + nums[j]; 
                if (sum == target) {
                    int index1 = hm.get(nums[i]) + 1;
                    int index2 = hm.get(nums[j]) + 1;
                    if (index1 == index2) // if nums[i] = nums[j] and i != j
                        index2 = findIndex(constant, nums[i], index1) + 1;
                    if (index2 > index1)
                        return new int[] {index1, index2};
                    else
                        return new int[] {index2, index1};
                }
                else if (sum > target)
                    break;
            }
        }
        assert false; // program should not come here according to the assumption of question
        return null;
    }
    
    private int findIndex(int[] nums, int target, int origin) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target && i != origin)
                return i;
        }
        return -1;
    }
    */
    
    /** Solution2 : O(n) */
    public int[] twoSum(int[] nums, int target) {
        if (nums == null || nums.length == 0)
            return null;
        HashMap<Integer, Integer> tracker = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; i++) {
            if (tracker.containsKey(nums[i])) {
                int left = tracker.get(nums[i]);
                return new int[] {left + 1, i + 1};
            }
            else {
                tracker.put(target - nums[i], i);
            }
        }
        assert false;
        return null;
    }
}

上面的是我的解法。比最早的做法好处在于,我一开始排了个序,所以当nums[i] + nums[j] > target时我就可以停止搜索了。但同样的,排序之后index也乱了,所以我采用了HashMap来解决这个问题。
然后又引入了一个新的问题。nums数组里面会有value重复。那么index就会被覆盖。所以当我发现value重复时,我需要到原数组中找到另外一个同value不同key的index。
所以我还需要将原数组拷贝一份后再排序,打乱index。
这么做复杂度虽然仍是O(n^2),但系数会小很多。
然后我使用到了Arrays.copyOf(...)
以前我一直在想,怎么给数组排序后还能准确找到他的原index。这道题木我的做法不失为一种好的解决方法。先拷贝一份原数组。然后将原数组插入到HashMap中。之后再排序。然后相应的操作再从HashMap中取出index。如果出现重复value的现象,再利用拷贝数组进行相应的操作。
虽然显得有些麻烦。
然后注意一个小细节。
我在最后返回null之前,有这么一句,
assert false;
这样的化当我允许使用assert时,如果程序跑到这里就一定会报错的。
因为我的假设是,程序不可能跑到这里。
这么一种做法可以广泛应用于代码中,使debug更加简单。
还学习到了一个命名,
tracker, good name
然后我看到了这个O(n)的解法,的确很巧妙。
赞一个。

Anyway, Good luck, Richardo!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容