代码随想录第二天|977有序数组平方209长度最小的子数组59螺旋矩阵II|01笔记

162 阅读2分钟
  • 977.有序数组的平方

  • 代码随想录 (programmercarl.com)
  • 第一印象

    • 这题看完之后的第一想法就是,如果没有负数存在的话,就是单纯的算下平方了。但是有了负数之后,就要考虑如何处理负数部分相反的顺序了。也许可以使用双指针。
  • 讲解观后感

    • 解题的逻辑大致想明白之后。还有一步就是如何构建代码。需要那些变量、容器等。根据思路,我们需要前后两个指针来进行原数组数值的比较;并且,我们还需要一个指针来倒序插入新数组的数值。
  • 解题代码

  •     func sortedSquares(nums []int) []int {
            n := len(nums)
            var l, r, k = 0, n-1, n-1
            ans := make([]int, n)
        
            for l<=r {
                
                if nums[l]*nums[l] > nums[r]*nums[r] {
                    ans[k] = nums[l]*nums[l]
                    l++
                    k--
                } else {
                    ans[k] = nums[r]*nums[r]
                    r--
                    k--
                }
            }
            return ans
        }
    
  • 209

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 考虑到一种暴力的思路,一个数遍历一遍、一对数字遍历一遍、三个数遍历一遍。。。出现符合就返回当前数量。思考下这种方法在面对不存在解的时候太过浪费了。
  • 于是考虑可以用两个指针滑动出结果,但是应该会有很多细节需要处理。
  • 讲解观后感

  • 看到了另外一种暴力解法。是用第一个数字位置固定后进行遍历的方法。
  •     class Solution {
        public:
            int minSubArrayLen(int s, vector<int>& nums) {
                int result = INT32_MAX; // 最终的结果
                int sum = 0; // 子序列的数值之和
                int subLength = 0; // 子序列的长度
                for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
                    sum = 0;
                    for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
                        sum += nums[j];
                        if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                            subLength = j - i + 1; // 取子序列的长度
                            result = result < subLength ? result : subLength;
                            break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                        }
                    }
                }
                // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
                return result == INT32_MAX ? 0 : result;
            }
        };
    
  • 时间复杂度:O(n^2) 空间复杂度:O(1)
    后面力扣更新了数据,暴力解法已经超时了。
  • 关于滑动窗口方法的构建

  • 讲解提供了我们做题中如何实际的一步一步分解问题并逐一攻克的范式。当一开始能想到解题的大致方法是用两个指针遍历一次我们的数组的时候,我们接下来就应该考虑这个一次遍历应该是哪一个指针了。接下来我们就要考虑如何让另一个指针移动。于是就顺理成章的引出了我们的窗口范围大小、窗口内数值之和等需要定义的变量。另外,由于我们需要的得到的是最小值,所以不能忘了定义答案变量的时候要谨慎。
  • 解题代码

  •     func minSubArrayLen(target int, nums []int) int {
            var l, sum = 0, 0
            var wl = len(nums) + 1
            var ans = len(nums) + 1
            for i:=0;i<len(nums);i++ {
                sum += nums[i]
                for sum>=target {
                    wl = i-l+1
                    if wl < ans {
                        ans = wl
                    }
                    sum -= nums[l]
                    l++ 
                }
            }
            if ans == len(nums) + 1 {
                return 0
            } else {
                return ans
            }
        }
    
  • 59螺旋矩阵

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 这题可以看出不需要特殊的算法,只要按照顺序一个一个往矩阵中填数即可。但是如何构建合理的循环逻辑,应该会有十分多的判定条件需要抉择。自己先尝试了一个大致的结构。然而发现终止条件和变化关系很难处理。
  •     func generateMatrix(n int) [][]int {
            int edge = n - 1
            int round = 0
            var ans = make([][]int,n)
            for i := 0; i < n; i++ {
                ans[i] = make([]int, n)
            }
            var count = 1
            for edge;edge>=0;edge-=2 {
                for h:=0;h<edge;h++ {
                    ans[][] = count
                    count++
                }
                for i:=0;i<edge;i++ {
                    ans[][] = count
                    count++
                }
                for j:=0;j<edge;j++ {
                    ans[][] = count
                    count++
                }
                for k:=0;k<edge;k++ {
                    ans[][] = count
                    count++
                }
        
            }
        }
    
  • 讲解观后感

  • 循环不变量的重要性再次被提及。左闭右开、左闭右闭的选择会影响代码的结构。并且起始位置、末尾位置、圈数、数字大小等边界条件等变量,也体现了代码的实现需要能够准确的满足其运行的定义。
  • 代码实现

  • 左闭右开:
  •     func generateMatrix(n int) [][]int {
        	startx, starty := 0, 0
        	var loop int = n / 2
        	var center int = n / 2
        	count := 1
        	offset := 1
        	res := make([][]int, n)
        	for i := 0; i < n; i++ {
        		res[i] = make([]int, n)
        	}
        	for loop > 0 {
        		i, j := startx, starty
        
        		//行数不变 列数在变
        		for j = starty; j < n-offset; j++ {
        			res[startx][j] = count
        			count++
        		}
        		//列数不变是j 行数变
        		for i = startx; i < n-offset; i++ {
        			res[i][j] = count
        			count++
        		}
        		//行数不变 i 列数变 j--
        		for ; j > starty; j-- {
        			res[i][j] = count
        			count++
        		}
        		//列不变 行变
        		for ; i > startx; i-- {
        			res[i][j] = count
        			count++
        		}
        		startx++
        		starty++
        		offset++
        		loop--
        	}
        	if n%2 == 1 {
        		res[center][center] = n * n
        	}
        	return res
        }
    
  • 左闭右闭
  •     func generateMatrix(n int) [][]int {
            top, bottom := 0, n-1
            left, right := 0, n-1
            num := 1
            tar := n * n
            matrix := make([][]int, n)
            for i := 0; i < n; i++ {
                matrix[i] = make([]int, n)
            }
            for num <= tar {
                for i := left; i <= right; i++ {
                    matrix[top][i] = num
                    num++
                }
                top++
                for i := top; i <= bottom; i++ {
                    matrix[i][right] = num
                    num++
                }
                right--
                for i := right; i >= left; i-- {
                    matrix[bottom][i] = num
                    num++
                }
                bottom--
                for i := bottom; i >= top; i-- {
                    matrix[i][left] = num
                    num++
                }
                left++
            }
            return matrix
        }
    
  • 左闭右闭的实现方式根据完整代码能够更容易读懂。但是构建过程中如何准确地把握变量变化的位置十分困难,需要清晰的思路。四个边界值的定义,有一点双指针的意味。