目录
1. 二分查找(704)
【题目描述】
在一个有序无重复元素的数组 nums 中,寻找一个元素 target ,如果找到了就返回对应的下标,如果没找到就返回 -1 。
【示例】
Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 exists in nums and its index is 4
【思路】
要在二分查找的过程中保持“不变量”——在 while 循环中,每一次边界的处理都根据区间的定义来操作,这就是“循环不变量”规则。
【Go代码】
func search(nums []int, target int) int {
low := 0
high := len(nums) - 1
var mid int
for (low <= high) {
mid = (low + high) / 2
if (nums[mid] == target) {
return mid
} else if (nums[mid] < target) {
low = mid + 1
} else {
high = mid - 1
}
}
return -1
}
【性能分析】
时间复杂度:O(logn)
空间复杂度:O(1)
2. 移除元素(27)
【题目描述】
原地移除数组中所有等于 val 的元素,要求不能使用额外的辅助空间,返回移除元素后新数组的 size 。
【示例】
Input: nums = [3,2,2,3], val = 3
Output: 2, nums = [2,2,_,_]
Explanation: Your function should return k = 2, with the first two elements of nums being 2.
It does not matter what you leave beyond the returned k (hence they are underscores).
【思路】双指针法
【Go代码】
func removeElement(nums []int, val int) int {
i := 0
for j := 0; j < len(nums); j++ {
if nums[j] != val {
nums[i] = nums[j]
i++
}
}
return i
}
【性能分析】
时间复杂度:O(n)
空间复杂度:O(1)
3. 长度最小的子数组(209)
【题目描述】
在一个正整数数组 nums 中找到最小长度的连续子数组,使子数组元素之和大于或等于 s 。返回满足条件的连续子数组的最小长度,如果没找到则返回 0 。
【示例】
Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: The subarray [4,3] has the minimal length under the problem constraint.
【思路】滑动窗口
【Go代码】
func minSubArrayLen(target int, nums []int) int {
i := 0 // 滑动窗口的起始位置
sum := 0 // 滑动窗口的数值之和
result := len(nums) + 1
for j := 0; j < len(nums); j++ {
sum += nums[j]
for sum >= target {
subLength := j - i + 1 // 滑动窗口的长度
if subLength < result {
result = subLength
}
sum -= nums[i]
i++
}
}
if result == len(nums) + 1 {
return 0
} else {
return result
}
}
【性能分析】
时间复杂度:O(n)
空间复杂度:O(1)
4. 螺旋矩阵II(59)
【题目描述】
给出一个正整数 n ,按从外向内的螺旋顺序打印 1 到 的所有数值。
【示例】
Input: n = 3
Output: [[1,2,3],[8,9,4],[7,6,5]]
【思路】循环不变量规则
【Go代码】
func generateMatrix(n int) [][]int {
startx, starty := 0, 0 // 定义每循环一个圈的起始位置
loop := n / 2 // 圈数
count := 1 // 赋值
offset := 1 // 每一圈都需要控制每条边的长度
var i int
var j int
// 创建二维数组
result := make([][]int, n)
for k := 0; k < n; k++ {
result[k] = make([]int, n)
}
for loop > 0 {
i = startx
j = starty
// 下面4个for就是循环一圈
// 从左到右填充上行
for j = starty; j < starty + n - offset; j++ {
result[i][j] = count
count++
}
// 从上到下填充右列
for i = startx; i < startx + n - offset; i++ {
result[i][j] = count
count++
}
// 从右到左填充下行
for j > starty {
result[i][j] = count
count++
j--
}
// 从下到上填充左列
for i > startx {
result[i][j] = count
count++
i--
}
// 下一圈的起始位置要各自加1
// 例如:第一圈的起始位置是 (0,0),第二圈的起始位置是 (1,1)
startx++
starty++
offset += 2 // 用于控制每一圈中每条边的长度
loop--
}
if n % 2 == 1 {
mid := n / 2
result[mid][mid] = count
}
return result
}
【性能分析】
时间复杂度:O()
空间复杂度:O()