算法- 数组2

111 阅读3分钟

题目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))")

数组算法总结:

  1. 注意处理边界条件,按照随想录的开闭原则来理解就好。典型案例 就是二分法 和 螺旋矩阵。
  2. 不能只看题解,必须自己动手。
    自己一写就会发现很多容易疏漏的细节点,这些也是需要练习的。
    比如 长度最小子数组 里while循环递进left节点、螺旋矩阵自己写的时候错误陷入到找行列规律, (如果真的找到,一次m*n的遍历应该就结束了😂)
  3. 坚持刷。