题目1: 209.长度最小的子数组
思路:
不看题解思路:
看到滑动窗口提示词了, 往细节想想。
设置左右指针,初始化为0。 设置最小数组长度初始化为int最大值。
开始遍历
退出条件,右指针到头了。
如果 左右指针累加 小于于目标值,右指针后移(这里注意处理如果左右指针相等,不要重复加)
如果 左右指针累加 大于等于目标值,左指针后移(这里注意处理如果左右指针相等,不要重复加)
分为几种case处理
1. 如果左右指针相等,同时后移
2. 左右指针不等, 左指针后移, 同时用左右指针差值 更新 最小数组长度(取小值)
自己尝试
/*
* @lc app=leetcode.cn id=209 lang=swift
*
* [209] 长度最小的子数组
*/
// @lc code=start
class Solution {
func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
var left = 0
var right = 0
var res = Int.max
var accum = nums[0]
// 可优化的点:右指针指index为1
while right < nums.count {
if accum < target {
right += 1
if right == nums.count { break }
accum += nums[right]
} else {
if right == left {
return 1
} else {
res = min(res, right - left + 1)
accum -= nums[left]
left += 1
}
}
}
return res == Int.max ? 0 : res
}
}
// @lc code=end
题解看完,滑动窗口用的是起始值 + 窗口长度来标记。 我的初始思路是窗口起始值+窗口结束值。
对比一下, 还是起始值+长度统计方便些。
精髓在于中间的while循环,可以一次把窗口缩短到目标值以下。
class Solution {
func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
var left = 0
var res = Int.max
var sum = 0
for i in 0..<nums.count {
sum += nums[i]
while sum >= target {
res = min(res, i - left + 1)
sum -= nums[left]
left += 1
}
}
return res == Int.max ? 0 : res
}
}
题目2:59.螺旋矩阵II
思考: 没有太好的思路,感觉暴力的话 也比较费劲。
题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。
看完题解的确是暴力解,但是要捋顺遍历思路。
/*
* @lc app=leetcode.cn id=59 lang=swift
*
* [59] 螺旋矩阵 II
*/
// @lc code=start
class Solution {
func generateMatrix(_ n: Int) -> [[Int]] {
// 轮次
var loop = 0
let line = [Int](repeating: 0, count: n)
var matrix = [[Int]](repeating: line, count: n)
var tag = 1
while loop < ((n + 1) / 2) {
if tag == n * n {
matrix[loop][loop] = tag
break
}
for i in loop..<(n - loop - 1) {
matrix[loop][i] = tag
tag += 1
}
for i in loop..<(n - loop - 1) {
matrix[i][n - loop - 1] = tag
tag += 1
}
for i in loop..<(n - 1 - loop) {
matrix[n - loop - 1][n - 1 - i] = tag
tag += 1
}
for i in loop..<(n - loop - 1) {
matrix[n - 1 - i][loop] = tag
tag += 1
}
loop += 1
}
return matrix
}
}
// @lc code=end
// 按照圈画
题目3:区间和
感受写区间和的计算方式
class Solution {
func generateMatrix(_ n: [Int]) -> [Int] {
var sum = 0
var res = [Int]()
for i in 0..<n.count {
sum = sum + n[i]
res.append(sum)
}
return res
}
}
let sum = Solution().generateMatrix([1, 2, 3, 4, 5])
// 计算两个元素之间的和。左开右闭
print("\(sum[4] - sum[2])")
题目4. 开发商购买土地
func main(_ nums: [[Int]]) -> Int {
var res = Int.max
let m = nums.count
let n = nums[0].count
var sum = 0
var horizontal = [Int](repeating: 0, count: m)
for i in 0..<m {
for j in 0..<n {
horizontal[i] += nums[i][j]
sum += nums[i][j]
}
}
var vertical = [Int](repeating: 0, count: n)
for j in 0..<n {
for i in 0..<m {
vertical[j] += nums[i][j]
}
}
var horizontalCnt = 0
for item in horizontal {
horizontalCnt += item
res = min(res, abs(sum - (2 * horizontalCnt)))
}
var vreticalCnt = 0
for item in vertical {
vreticalCnt += item
res = min(res, abs(sum - (2 * vreticalCnt)))
}
return res
}
let input = [[1, 2, 3], [2, 1, 3], [1, 2, 3]]
print("\(main(input))")
数组算法总结:
- 注意处理边界条件,按照随想录的开闭原则来理解就好。典型案例 就是二分法 和 螺旋矩阵。
- 不能只看题解,必须自己动手。
自己一写就会发现很多容易疏漏的细节点,这些也是需要练习的。
比如 长度最小子数组 里while循环递进left节点、螺旋矩阵自己写的时候错误陷入到找行列规律, (如果真的找到,一次m*n的遍历应该就结束了😂) - 坚持刷。