题目链接:167.两数之和 II - 输入有序数组 - 力扣(LeetCode)
这题相对两数之和来说最大的区别就是数组按非递减顺序排列,依旧可以和两数之和一样使用暴力枚举和哈希表来进行解答,在这里不做赘述。见两数之和解答:力扣算法题:1. 两数之和_storykeep的博客-CSDN博客y
由于这是有个有序数组,可以利用有序数组的性质选用其他方法解答。
解法一:二分查找
先固定一个数,那么与之对应的另一个数的值就是确定的。由于这是一个有序数组,在有序数组中可以采用二分查找来确定要寻找的元素的位置。
二分查找使用两个标识来确定查找范围,每次取中间的值进行对比,确定目标值的范围,移动标识,缩小查找范围,不断二分,直到找到目标值,或确定查找范围内没有目标值停止。
JavaScript代码:
/**
* @param {number[]} numbers
* @param {number} target
* @return {number[]}
*/
var twoSum = function(numbers, target) {
const len=numbers.length
for(let i=0;i<len;i++){
const temp=target-numbers[i]
let left=i+1
let right=len-1
while(right>=left){
let mid=Math.floor((right-left)/2+left)
if(numbers[mid]===temp){
return [i+1,mid+1]
}else if(numbers[mid]>temp){
right=mid-1
}else{
left=mid+1
}
}
}
};
go语言代码:
func twoSum(numbers []int, target int) []int {
var left,rigth,mid int
for i,item := range numbers {
temp:=target-item
left=i+1
rigth=len(numbers)-1
for rigth>=left {
mid=left+(rigth-left)/2
if numbers[mid]==temp {
return []int{i+1,mid+1}
}else if numbers[mid]>temp {
rigth=mid-1
}else{
left=mid+1
}
}
}
return nil
}
时间复杂度:O(nlogn)
解法二:双指针
双指针分为快慢指针和对撞指针(左右指针),在这里采用对撞指针求解。
初始时左右指针分别指向数组的第一个和最后一个值,然后计算两指针之和,与目标值对比,根据对比结果移动左右指针,直至找到目标结果,或指针相撞。
JavaScript代码:
/**
* @param {number[]} numbers
* @param {number} target
* @return {number[]}
*/
var twoSum = function(numbers, target) {
let left=0;
let right=numbers.length-1
while(right>left){
if(numbers[left]+numbers[right]==target){
return [left+1,right+1]
}else if(numbers[left]+numbers[right]>target){
right--
}else{
left++
}
}
};
go语言代码:
func twoSum(numbers []int, target int) []int {
left:=0
right:=len(numbers)-1
for right>left {
if numbers[left]+numbers[right]==target {
return []int{left+1,right+1}
}else if numbers[left]+numbers[right]>target {
right--
}else{
left++
}
}
return nil
}
时间复杂度:O(n)