第一题 two-sum

来源:互联网 发布:c语言中的echo 编辑:程序博客网 时间:2024/06/05 18:29

题目描述

Problem:Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

题目要求是从一个向量中找出两个数的和能够与目标值匹配,由于问题的规模比较小,只是找两个数字,暂时还用不上动态规划、广度搜索之类的算法,但是朴素的暴力搜索肯定健壮性不够,Leetcode给出了三种解法。

第一种很自然能够想到的,暴力搜索,在向量中进行两层循环,算法的空间复杂度为O(1),时间复杂度为O(n^2),不是很理想。

public int[] solution(int[] nums, int target) {    for (int i = 0; i < nums.length; i++) {        for (int j = i + 1; j < nums.length; j++) {            if (nums[j] == target - nums[i]) {                return new int[] { i, j };            }        }    }}

第二种我们可以继续分析,为了找到合适的解最坏情况下是要遍历所有值,此时的时间复杂度为O(n),上面的暴力搜索瓶颈在查找的方案上,它进行了两次遍历,浪费了资源。而这种形式的查找,复杂度最低肯定是O(1),也就是哈希表,而哈希查找是建立在内存消耗的基础上的,把数据的下标和数据本身绑在一起构成节点形成键值联系,建立起hash_map,然后在哈希表中查找对应的键值。虽然降低了时间复杂度,但是提升了空间复杂度,变为了O(n)。总的来说,健壮性很好。

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

这道题作为leetcode的第一道题,非常有启示意义,这道题从常规意义上讲,并不是很难,但是这个题明显反应了逻辑思维的高度。我看到这个题第一眼想到的就是暴力搜索,不就是两次循环吗?没有看到出题人的想法,并没有什么常规意义上的简单题,逻辑严谨时,所有的题都能体现很多价值。

这道题如果从高一些的层次分析,直接根据数学原理,找出这道的算法极限,就能找出相对最健壮的算法。这道题明显是在有限数据中找合适解的题,合适解的寻找方法没什么可优化的,能够优化的就是这些数据的组织形式和查找方法,查找方法效率最高的肯定是哈希表,答案就呼之欲出了。

总的来说,这道题很有启发价值,要去思考和学习的地方还有很多。

原创粉丝点击