LeetCode题目
977.有序数组的平方
题目链接:Squares of a Sorted Array - LeetCode
双指针法
- 数组 A 有序,则平方之后最大值在数组两端,越靠近中间则平方越小
- 双指针法,设置 left, right 指向 A 两端,设置 index 指向 result 数组末尾
- if A[left] * A[left] > A[right] * A[right] { result[index--] = A[left] * A[left] }
- else { result[index--] = A[right] * A[right] }
代码如下:
func sortedSquares(nums []int) []int {
n := len(nums)
left, right, index := 0, n-1, n-1
result := make([]int, n)
for left <= right {
if nums[left]*nums[left] > nums[right]*nums[right] {
result[index] = nums[left] * nums[left]
left++
} else {
result[index] = nums[right] * nums[right]
right--
}
index--
}
return result
}
209.长度最小的子数组
题目链接:Minimum Size Subarray Sum - LeetCode
滑动窗口
- 使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个「窗口」
- 增加 right 指针扩大窗口 [left, right],直到窗口中的字符串符合要求
- 停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不再符合要求,同时,每次增加 left,都要更新一轮结果
代码如下:
func minSubArrayLen(target int, nums []int) int {
start := 0
result := len(nums) + 1
sum := 0
for end := 0; end < len(nums); end++ {
sum += nums[end]
for sum >= target {
subLen := end - start + 1
if subLen < result {
result = subLen
}
sum -= nums[start]
start++
}
}
if result == len(nums)+1 {
return 0
}
return result
}
59.螺旋矩阵II
题目链接:Spiral Matrix II - LeetCode
模拟法
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
代码如下:
func generateMatrix(n int) [][]int {
matrix := make([][]int, n)
for i := 0; i < n; i++ {
matrix[i] = make([]int, n)
}
startx, starty := 0, 0
loop := n / 2
mid := n / 2
count := 1
offset := 1
for loop > 0 {
i, j := startx, starty
// 上行从左到右(左闭右开)
for ; j < n-offset; j++ {
matrix[i][j] = count
count++
}
// 右列从上到下(左闭右开)
for ; i < n-offset; i++ {
matrix[i][j] = count
count++
}
// 下行从右到左(左闭右开)
for ; j > starty; j-- {
matrix[i][j] = count
count++
}
// 左列从下到上(左闭右开)
for ; i > startx; i-- {
matrix[i][j] = count
count++
}
startx++
starty++
offset++
loop--
}
if n%2 == 1 {
matrix[mid][mid] = count
}
return matrix
}
向量法
- 定义对应点的坐标为 (i, j),每次移动的向量为 (di, dj)
- 先向右移动,也就是此时的向量为 (0, 1)(注意这里使用行列为坐标,而不是笛卡尔坐标)
- 如果 A[(i + di) % n][(j + dj) % n] != 0,则需要转向
- 移动向量更改为 (dj, -di)
代码如下:
func generateMatrix(n int) [][]int {
// 生成二维数组
matrix := make([][]int, n)
for i := 0; i < n; i++ {
matrix[i] = make([]int, n)
}
// [i, j]为二维数组坐标,(di, dj)为移动方向向量
i, j, di, dj := 0, 0, 0, 1
for k := 1; k <= n*n; k++ {
matrix[i][j] = k
// 判断下一步是否需要转向,多加一个n是为了防止负数下标越界
if matrix[(i+di+n)%n][(j+dj+n)%n] != 0 {
di, dj = dj, -di
}
// 计算下一步填充坐标
i += di
j += dj
}
return matrix
}
总结
- 双指针法在数组相关算法中运用很广泛
- 滑动窗口算法好好理解一下
- 螺旋矩阵II中使用的向量法很有趣,该思想应该也可以运用到其他算法中