算法练习-第一天【数组】
数组
704.二分查找
看完题目的第一想法
一道很基础的二分查找题目,直接使用左闭右闭区间的方式开撸
func search(nums []int, target int) int {
left, right := 0, len(nums)-1
for left <= right {
mid := left + (right-left)/2
if nums[mid] > target {
right = mid - 1
} else if nums[mid] < target {
left = mid + 1
} else {
return mid
}
}
return -1
}
因为区间是左闭右闭,即[left, right],因此right取len(nums)-1是有意义的, 同理left<=right的等号也是有意义的。
根据判断条件nums[mid] > target 得知nums[mid]一定不等于target, 为了使得区间为[left, right]有意义,那么right需要取mid-1。
今日收获
巩固一下二分查找,思考下左闭右闭区间和左闭右开区间的含义。
左闭右开区间解法
func search(nums []int, target int) int {
left, right := 0, len(nums)
for left < right {
mid := left + (right-left)/2
if nums[mid] > target {
right = mid
} else if nums[mid] < target {
left = mid + 1
} else {
return mid
}
}
return -1
}
27.移除元素
看完题目的第一想法
搞清楚数组:数组是一块连续的内存,操作数组中的元素只能覆盖,不能单独删除某一个元素。
因此本道题可以使用双指针的方式来移动数组元素,以达到O(n)的时间复杂度。
package main
func removeElement(nums []int, val int) int {
slowIdx := 0
for fastIdx := 0; fastIdx < len(nums); fastIdx++ {
if nums[fastIdx] != val {
nums[slowIdx] = nums[fastIdx]
slowIdx++
}
}
return slowIdx
}
其中slowIdx指向新元素更新的位置,fastIdx用来寻找符合条件的元素。
也可以使用相向双指针的方法来确保移动最少的元素
package main
func removeElement(nums []int, val int) int {
lo, hi := 0, len(nums)-1
for lo <= hi {
for lo <= hi && nums[lo] != val {
lo++
}
for lo <= hi && nums[hi] == val {
hi--
}
if lo < hi {
nums[lo] = nums[hi]
lo++
hi--
}
}
// lo指向了移除之后数组的下一个元素
return lo
}
附上暴力解法
func removeElement(nums []int, val int) int {
n := len(nums)
for i := 0; i < n; i++{
if nums[i] == val{
for j := i+1; j < n; j++{ // 将所有数组向前移动
nums[j-1] = nums[j]
}
i--
n--
}
}
return n
}
暴力解法是找到一个nums[i]==val后,将i后面的所有元素向前移动一位,移动之后当前的i位置需要减一,数组长度减一。
今日收获
看到题目的时候想到了快慢指针的解法
依靠相向双指针可以减少数组的元素的移动。
遇到的困难
暴力解法时,记得每移除一个元素,数组的下标i也需要减一。
浙公网安备 33010602011771号