资讯专栏INFORMATION COLUMN

[Leetcode] Two Sum 两数和

pkhope / 288人阅读

摘要:如果存在该差值,说明存在两个数之和是目标和。而哈希表方法中的则可以换成。如果要求的不是两个数和和,而是找两个数之差为特定值的配对呢同样用哈希表可以解决。

Two Sum
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

暴力法 Brute Force 复杂度

O(1)空间 O(n^2)时间

思路

通过双重循环遍历数组中所有元素的两两组合,当出现符合的和时返回两个元素的下标

注意

内层循环要从外层循环下标加一开始,避免遍历到两个相同的元素

代码
public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        if(nums.length < 2){
            return result;
        }
        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;
                    return result;
                }
            }
        }
        return result;
    }
}
哈希表 Hash Table 复杂度

O(n)空间 O(n)时间

思路

第一次遍历数组先将所有元素和它的下标作为key-value对存入Hashmap中,第二次遍历数组时根据目标和与当前元素之差,在Hashmap中找相应的差值。如果存在该差值,说明存在两个数之和是目标和。此时记录下当前数组元素下标并拿出Hashmap中数组元素下标即可。Hashmap获取元素的时间复杂度是O(1),所以总的时间复杂度仍不超过O(n)。

注意

判定是否存在该差值时,要同时判断该差值的下标是不是当前遍历的元素下标,以避免重复

哈希表作为一个Collection,初始化时请注意声明Key和Value的类型

代码
public class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map map = new HashMap();
        int[] res = new int[2];
        for(int i = 0; i < nums.length; i++){
            int diff = target - nums[i];
            if(map.containsKey(nums[i])){
                res[0] = map.get(nums[i]) + 1;
                res[1] = i + 1;
            }
            map.put(diff, i);
        }
        return res;
    }
}

2018/2 更新

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        numsMap = {}
        for index in range(0, len(nums)):
            num1 = nums[index]
            num2 = target - num1
            if num2 in numsMap:
                return [index, numsMap[num2]]
            else:
                numsMap[num1] = index

2018/10

func twoSum(nums []int, target int) []int {
    m := make(map[int]int)
    result := make([]int, 2)

    for i := 0; i < len(nums); i++ {
        var curr = nums[i]
        var diff = target - curr
        result[0] = i
        if _, ok := m[diff]; ok {
            result[1] = m[diff]
            return result
        } else {
            m[curr] = i
        }
    }
    return result
}
排序双指针法 Sorting with Two Pointers 复杂度

O(n)空间 O(nlogn)时间

思路

首先将原数组复制一遍,对新数组进行排序。排序后将双指针指向头部与尾部元素,进行迭代。如果双指针指向元素之和大于目标和,则将尾部指针向前移一位,反之则将头部指针向后移一位,直到双指针指向元素之和等于目标和,记录这两个元素的值,然后再遍历一遍旧数组,找出这两个元素的下标。

注意

该方法需要先将结果数组都初始化为-1,否则在遍历旧数组时无法去除重复,可能会将两个下标都存入同一个结果中

代码
private ArrayList> twoSum(int[] nums, int target){
    int left = 0, right = nums.length - 1;
    ArrayList> res = new ArrayList>();
    while(left < right){
        if(nums[left] + nums[right] == target){
            ArrayList curr = new ArrayList();
            curr.add(nums[left]);
            curr.add(nums[right]);
            res.add(curr);
            do {
                left++;
            }while(left < nums.length && nums[left] == nums[left-1]);
            do {
                right--;
            } while(right >= 0 && nums[right] == nums[right+1]);
        } else if (nums[left] + nums[right] > target){
            right--;
        } else {
            left++;
        }
    }
    return res;
}
后续 Follow Up

Q:如果不需要返回数组下标,只用返回两个数本身呢?
A:如果只用返回两个数本身,排序双指针法可以做到O(1)空间,时间复杂度仍是O(nlogn)。而哈希表方法中的HashMap则可以换成HashSet。

Q:如果要求的不是两个数和和,而是找两个数之差为特定值的配对呢?
A:同样用哈希表可以解决。如果要不用空间的话,也可以先排序,然后将两个指针指向头,两个数差小于目标时,将后指针向后移,否则将前指针向后移。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64394.html

相关文章

  • LeetCode 167:两数之和 II - 输入有序数组 Two Sum II - Input a

    摘要:公众号爱写给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值和,其中必须小于。示例输入输出解释与之和等于目标数。 公众号: 爱写bug(ID:icodebugs) 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。...

    张春雷 评论0 收藏0
  • LeetCode 167:两数之和 II - 输入有序数组 Two Sum II - Input a

    摘要:公众号爱写给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值和,其中必须小于。示例输入输出解释与之和等于目标数。 公众号: 爱写bug(ID:icodebugs) 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。...

    Me_Kun 评论0 收藏0
  • LeetCode 2:两数相加 Add Two Numbers

    摘要:给出两个非空的链表用来表示两个非负的整数。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。需要考虑到两个链表长度不同时遍历方式链表遍历完成时最后一位是否需要进一位。 ​给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 ...

    diabloneo 评论0 收藏0
  • LeetCode 2:两数相加 Add Two Numbers

    摘要:给出两个非空的链表用来表示两个非负的整数。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。需要考虑到两个链表长度不同时遍历方式链表遍历完成时最后一位是否需要进一位。 ​给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 ...

    Towers 评论0 收藏0
  • LeetCode.1 两数之和(Two Sum)(JS)

    摘要:开坑,以后每周刷一两道一题目两数之和给定一个整数数组和一个目标值,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。但是,你不能重复利用这个数组中同样的元素。 开坑,以后每周刷一两道LeetCode 一、题目 两数之和: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应...

    Gu_Yan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<