283 移动零,167. 两数之和 II - 输入有序数组
移动零
不能复制数组,考虑计数0的个数,当前数组元素前存在counts个0元素,该数组元素向前移动counts个值,最后将counts个0放置在数组最后
func moveZeroes(nums []int) {
var counts int
for i:=0;i<len(nums);i++{
if nums[i]==0{
counts++
continue
}
nums[i-counts%len(nums)]=nums[i]
}
for j:=len(nums)-1;counts>0;j-- {
nums[j]=0
counts--
}
}
使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。
注意到以下性质:
- 左指针左边均为非零数;
- 右指针左边直到左指针处均为零。
- 因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变
func moveZeroes(nums []int) {
left, right, n := 0, 0, len(nums)
for right < n {
if nums[right] != 0 {
nums[left], nums[right] = nums[right], nums[left]
left++
}
right++
}
}
两数之和 II - 输入有序数组
二分查找方法:
在数组中找到两个数,使得它们的和等于目标值,可以首先固定第一个数,然后寻找第二个数,第二个数等于目标值减去第一个数的差。利用数组的有序性质,可以通过二分查找的方法寻找第二个数。为了避免重复寻找,在寻找第二个数时,只在第一个数的右侧寻找。
func twoSum(numbers []int, target int) []int {
for i:=0;i<len(numbers);i++{
low,high:=i+1,len(numbers)-1
for low<=high{
mid:=low+(high-low)/2
if numbers[mid]==target-numbers[i]{
return []int{i+1,mid+1}
}else if numbers[mid]>target-numbers[i]{
high=mid-1
}else{
low=mid+1
}
}
}
return []int{-1,-1}
}
双指针
初始时两个指针分别指向第一个元素位置和最后一个元素的位置。每次计算两个指针指向的两个元素之和,并和目标值比较。如果两个元素之和等于目标值,则发现了唯一解。如果两个元素之和小于目标值,则将左侧指针右移一位。如果两个元素之和大于目标值,则将右侧指针左移一位。移动指针之后,重复上述操作,直到找到答案。
func twoSum(numbers []int, target int) []int {
low, high := 0, len(numbers) - 1
for low < high {
sum := numbers[low] + numbers[high]
if sum == target {
return []int{low + 1, high + 1}
} else if sum < target {
low++
} else {
high--
}
}
return []int{-1,-1}
}