方法一:暴力
先从0
开始枚举下标i
,然后从i+1
开始枚举下标j
,判断nums[i]+nums[j] == target
即可
复杂度分析
时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( 1 ) O(1) O(1)
Java
class Solution {
public int[] twoSum(int[] nums, int target) {
int n = nums.length;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (nums[i] + nums[j] == target) {
return new int[]{i, j};
}
}
}
return new int[]{};
}
}
Golang
func twoSum(nums []int, target int) []int {
for i, x := range nums {
for j := i + 1; j < len(nums); j++ {
if x + nums[j] == target {
return []int{i, j}
}
}
}
return []int{}
}
方法二:哈希
题目条件时找到nums[i]+nums[j] == target
,也可以等效看成nums[j] == target-nums[i]
,暴力做法在循环的时候只是比较了一下,如果我们在遍历到nums[i]
的时候把nums[j]
和下标j记录到一个HashMap
中,每次循环到nums[i]
的时候只需要判断一下map
是否存在target-nums[j]
即可。哈希表的查找效率是O(1)
,替代掉了一重循环。
搜索空间的完备性?
遍历到每个数a
的时候都会和a
前面的记录的数做比较,在a
后面的数b
会在遍历到b
的时候回来和b
之前包括a
在内的所有数的记录做比较,所以一个数和前后的数都做了比较。
复杂度分析
时间复杂度为 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; ++i){
int temp = target - nums[i];
if(map.containsKey(temp)){
return new int{i, map.get(temp)};
}
map.put(nums[i], i);
}
return new int[]{};
}
}
func twoSum(nums []int, target int) []int {
idx := map[int]int{}
for i, x := range nums {
if j, ok := idx[target - x]; ok {
return []int{i, j}
}
idx[x] = i
}
return []int{}
}
扩展:如果数组是有序的还需要借助哈希表结构吗?
如果数组已经事先排好序了,我们可以用相向双指针的方法优化到时间复杂度
O
(
n
)
O(n)
O(n),空间复杂度
O
(
1
)
O(1)
O(1)
思路是定义两个指针left
和right
,先选择指向最左边和最右边的数,即最大和最小的数,判断numbers[left]+numbers[right]==tagert
,如果大于,那么numbers[left]
右边所有的数都比numbers[left]
大,这些数加上numbers[right]
更会大,这时我们只能把right--
;反之如果是小于,那么numbers[right]
左边数都比numbers[right]
小,这些数加上numbers[left]
的结果会更小,这时我们只能把left++
。
搜索空间的完备性?
力扣题解里有位大佬动图表示这题搜索缩减搜索空间的本质,非常值得一看传送门
class Solution {
public int[] twoSum(int[] numbers, int target) {
int left = 0, right = numbers.length - 1;
while(left < right) {
int sum = numbers[left] + numbers[right];
if(sum == target) {
break;
} else if(sum < target) {
left++;
} else {
right--;
}
}
return new int[]{left + 1, right + 1};
}
}
func twoSum(numbers []int, target int) []int {
left, right := 0, len(numbers) - 1
for {
sum := numbers[left] + numbers[right]
if sum == target {
return []int{left + 1, right + 1}
}
if sum > target {
right--
} else {
left++
}
}
}