算法-两数之和

# 两数之和

来源: https://leetcode.cn/problems/two-sum/ (opens new window)

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

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

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

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

解题思路:

关键点在于交换律思路

点击查看代码




















 

 

 

























/**
 * 两数之和
 * @param {number[]} nums 
 * @param {number} target 
 * @returns number[]
 * 
 * 双循环
 * 时间复杂度 O(n**2)
 * 空间复杂度 O(1)
 * 
 * map映射
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */
const twoNum = (nums, target) => {
  // 暴力解, 双循环
  // for (let i = 0, len = nums.length; i < len; i++) {
  //   for (let j = i + 1; j < len; j++) {
  //     if (nums[i] + nums[j] === target) {
  //       return [i, j]
  //     }
  //   }
  // }
  // return []

  // map 映射
  const map = new Map()
  for (let i = 0, len = nums.length; i < len; i++) {
    const x = target - nums[i]
    if (map.has(x)) {
      return [map.get(x), i]
    }
    map.set(nums[i], i)
  }
  return []
}

const twoSum2 = (nums, target) => {
  // if (nums.length === 0) return false
  // const dict = Object.fromEntries(nums.map(n => [n, true]))
  // return nums.some(n => dict[target - n])

  // 2. 不考虑性能, 直接 some
  return nums.some(n => nums.includes(target - n))
}

console.log(twoNum([3,2,4], 6))
console.log(twoSum2([1, 1], 2))
// [1,2]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# TS 版本

点击查看代码
const twoSumFunc = (
  nums: number[],
  target: number,
): boolean => {
  // if (nums.length === 0) return false
  // const dict = Object.fromEntries(nums.map(n => [n, true]))
  // return nums.some(n => dict[target - n])

  // 2. 不考虑性能, 直接 some
  return nums.some(n => nums.includes(target - n))
}

const twoSum = (
  nums: number[],
  target: number,
  set: Set<number> = new Set([])
): boolean => {
  if (nums.length === 0) return false
  const delta = target - nums[0]
  return set.has(delta) ? true : twoSum(nums.slice(1), target, new Set([...set, nums[0]]))
}

type ToTuple<L extends number, T extends any[] = []> =
  T extends { length: L } ? T : ToTuple<L, [...T, any]>

type Sub<A extends number, B extends number> =
  ToTuple<A> extends [...ToTuple<B>, ...infer Tail] ? Tail['length'] : -1
type Tail<T> = T extends [any, ...infer Tail] ? Tail : []

type TTwoSum<N extends number[], T extends number, Set extends any = []> =
  N['length'] extends 0
    ? never
    : Set extends Sub<T, N[0]>
      ? true
      : TTwoSum<Tail<N>, T, Set | N[0]>

type Expect<T extends true> = T
type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) 
    ? true
    : false

type Cases = [
  Expect<Equal<TTwoSum<[2, 7, 11, 15], 9>, true>>,
  Expect<Equal<TTwoSum<[2, 7, 11, 15], 2>, never>>,
]
// [true, true]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48