算法分享:两数之和

76 阅读2分钟

题目:1. 两数之和

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104 10^4

  • 109 10^9 <= nums[i] <= 109 10^9

  • 109 10^9 <= target <= 109 10^9

  • 只会存在一个有效答案

进阶: 你可以想出一个时间复杂度小于 O(n2) O(n^2) 的算法吗?

解题思路

这道题最优的算法时间复杂度是O(n)O(n)

顺序扫描数组,对每一个元素,在 map 中找能组合给定值的另一半数字,如果找到了,直接返回 2 个数字的下标即可。如果找不到,就把这个数字存入 map 中,等待扫到“另一半”数字的时候,再取出来返回结果。

实现代码

func twoSum(nums []int, target int) []int {
    diff := make(map[int]int, 0)

    for i := 0; i < len(nums); i++ {
        idx, ok := diff[target-nums[i]]
        if ok {
            return []int{idx, i}
        }

        diff[nums[i]] = i
    }

    return []int{}
}

复杂度分析

  • 时间复杂度: O(n)O(n), 其中 N N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) O(1) 地寻找 target - x

  • 空间复杂度: O(n)O(n), 其中 N N 是数组中的元素数量。主要为哈希表的开销。

单元测试

package leetcode

import (
    "testing"

    "github.com/stretchr/testify/assert"
)

func Test_twoSum(t *testing.T) {
    assert := assert.New(t)

    type args struct {
        nums   []int
        target int
    }

    tests := []struct {
        args args
        want []int
    }{
        {
            args: args{nums: []int{2, 7, 11, 15}, target: 9},
            want: []int{0, 1},
        },
        {
            args: args{nums: []int{3, 2, 4}, target: 6},
            want: []int{1, 2},
        },
        {
            args: args{nums: []int{3, 3}, target: 6},
            want: []int{0, 1},
        },
    }

    for _, tt := range tests {
        actual := twoSum(tt.args.nums, tt.args.target)
        assert.Equal(tt.want, actual)
    }
}
  • 欢迎加入 令飞编程实战营 知识星球。P8 技术专家出品,12+ 高质量体系课、20+ 高质量实战项目,助你在 AI 浪潮中建立不可替代的技术竞争力,冲击百万年薪!实战营聚焦 Go、云原生、AI Infra 三大领域;
  • 欢迎关注 令飞编程,Go、云原生、AI Infra、职场干货不错过!回复「资料」可免费下载 Go、云原生等学习资料;
  • 我的 B 站:令飞编程,欢迎关注,会分享技术、职场和课程等视频内容。