《LeetCode-0001》 两数之和-TwoSum

https://leetcode-cn.com/problems/two-sum/

题目

给定一个整数数组nums 和一个目标值 target ,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路

暴力

最简单的一种思路,两层循环,两两相加后与target比较。但是循环的起点不同,第一个元素和后面的每个元素进行比较,第二个元素也是和它之后的元素进行比较,所以外层的循环起点为0,内层的循环起点则是由外层决定,若外层为i,则内层循环起点为i+1,这样也可以保证,不重复利用数组中同样的元素。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        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;
                    result[1] = j;
                }
            }
        }
        return result;
    }
}

哈希表

暴力方法之所以要循环两次,是因为我们需要找两个数的下标,采用哈希表的方法,在循环过程中存储下标,可以省去嵌套一次循环,但是找结果的方式与暴力方式不太一样。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (map.containsKey(complement)) {
                return new int[] { map.get(complement), i };
            }
            map.put(nums[i], i);
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

上面的暴力方法,是从前往后找另外一半,找到立刻返回,比如

int nums[] = new int[]{2, 7, 11, 15};

若target目标值为17,执行过程:

i,j 计算结果 是否匹配
0,1 9 NO
0,2 13 NO
0,3 17 YES

若是用哈希表的方式,可以理解为从当前循环点往前找另外一半,利用的是2+3=5,3+2=5,加法的交换律,不管从前往后还是从后往前,都是OK的。
执行过程:

i 是否匹配 单次循环结束后map
0 NO (2, 0)
1 NO (2, 0) , (7,1)
2 NO (2,0) , (7,1) , (11,3)
3 YES

总结

  1. 某些场景下,暴力方式可能速度更快,但是第二种方式整体时间复杂度更低。
  2. 第二种采用HashMap 的方式,当然也可以采用其他存储数值和下标的方式。
发布了159 篇原创文章 · 获赞 264 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/poorkick/article/details/90573159
今日推荐