《LeetCode-0001》 两数之和-TwoSum

    xiaoxiao2024-10-18  88

    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,19NO0,213NO0,317YES

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

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

    总结

    某些场景下,暴力方式可能速度更快,但是第二种方式整体时间复杂度更低。第二种采用HashMap 的方式,当然也可以采用其他存储数值和下标的方式。 onlyloveyd 认证博客专家 Android Kotlin OpenCV 个人公众号【OpenCV or Android】,热爱Android、Kotlin、Flutter和OpenCV。毕业于华中科技大学计算机专业,曾就职于华为武汉研究所。目前在三线小城市生活,专注Android、OpenCV、Kotlin、Flutter等有趣的技术。
    最新回复(0)