[代码随想录打卡]Day2:209.长度最小的子数组 59.螺旋矩阵II 区间和 开发商购买土地 总结

双指针:快慢指针、对撞指针、滑动窗口。相关博客:双指针算法详解(快慢指针、对撞指针、滑动窗口)

209.长度最小的子数组

题目:给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的
子数组
[numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
重点:需要明白长度是在哪个指针移动的时候更新的。这个题目中最小子数组的长度是在慢指针移动的时候更新的。
思想:双指针思想,遍历fast指针,然后每次都判断一下当前子数组是否满足题目要求,如果满足就进入while循环。while循环是用来移动slow指针的位置的,先计算子数组长度判断是否对最小长度进行更新,然后更新slow指针的位置。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //开始有新的理解了
        int sum = 0;
        int ans = 0;
        for(int slow = 0, fast = 0; fast < nums.length; fast++){
            //其中j就是快指针
            sum+=nums[fast];
            while(sum >= target){
                if(ans > fast-slow+1 || ans == 0 ){
                    ans = fast-slow+1;
                }
                sum -= nums[slow];
                slow++;
            }

        }
        return ans;
    }
}
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        slow = 0
        ans = 0
        numSum = 0
        for fast in range(len(nums)):
            numSum += nums[fast]
            while(numSum >= target):
                if(ans > fast-slow+1 or ans == 0):
                    ans = fast - slow +1
                numSum -= nums[slow]
                slow+=1
        return ans

好像很多乍一看可以用两层for循环进行暴力求解的,都可以试试双指针。就是双指针的初始化的位置,移动的条件需要思考一下,这些是不同的。

59.螺旋矩阵II

题目:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
在这里插入图片描述
重点:循环不变量。区间定义。(是左闭右闭还是左闭右开,在循环中不要发生变化。)在这个螺旋数组中区间定义就是左闭右开。
思想:一次循环就是一圈,每一圈四个方向。这个循环和上一个循环之间的差异是什么,什么变化了。

class Solution {
    public int[][] generateMatrix(int n) {
        int count=1;
        int offset = 1;
        int startx = 0;
        int starty = 0;
        int i=0, j=0;
        int[][] nums = new int[n][n];
        for(int iter=0; iter <n/2;iter++){//转这些圈
            for(j = starty; j < n-offset;j++){
                nums[startx][j] = count++; 
            }
            for(i = startx; i < n-offset; i++){
                nums[i][j] = count++;
            }
            for(; j>starty;j--){
                nums[i][j] = count++;
            }
            for(; i>startx;i--){
                nums[i][j] = count++;
            }
            startx++;
            starty++;
            offset++;
        }
        if(n%2==1){
            nums[n/2][n/2] = count;
        }
        return nums;
    }
}

有很多人说就是这个不好的一点就是变量定义的太多,但是我感觉虽然变量定义多,看起来有点冗余,但是好理解。下面是我自己减少了变量后写的。

class Solution {
    public int[][] generateMatrix(int n) {
        int count = 1;
        int i=0, j=0;
        int[][] matrix = new int[n][n];
        for(int circles=0; circles < n/2; circles++){
            for(j=circles; j < n - circles-1; j++){
                matrix[circles][j] = count++;
            }
            for(i=circles; i < n - circles-1; i++){
                matrix[i][j] = count++;
            }
            for(; j > circles; j--){
                matrix[i][j] = count++;
            }
            for(; i > circles; i--){
                matrix[i][j] = count++;
            }

        }
        if(n%2==1){
            matrix[n/2][n/2] = count;
        }
        return matrix;
    }
}

下面是python版本,感觉python由于while和for和JAVA,C++不同就得多思考一下,用for的话得思考清楚四个边角的坐标。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        count = 1
        q = 0
        i = 0
        j = 0
        matrix = [[0 for _ in range(n)] for _ in range(n)]
        #转多少圈
        while(q < n/2):
            j = q
            i = q
            while(j < n-q-1):
                matrix[i][j] = count
                count+=1
                j+=1
            while(i < n-q-1):
                matrix[i][j] = count
                count+=1
                i+=1
            while(j > q):
                matrix[i][j] = count
                count+=1
                j-=1
            while(i > q):
                matrix[i][j] = count
                count+=1
                i-=1
            q += 1
        if(n%2 == 1):
            matrix[i][j] = count
        return matrix

下面是代码随想录上的,我就粘贴一个了。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[0] * n for _ in range(n)]
        startx, starty = 0, 0               # 起始点
        loop, mid = n // 2, n // 2          # 迭代次数、n为奇数时,矩阵的中心点
        count = 1                           # 计数

        for offset in range(1, loop + 1) :      # 每循环一层偏移量加1,偏移量从1开始
            for i in range(starty, n - offset) :    # 从左至右,左闭右开
                nums[startx][i] = count
                count += 1
            for i in range(startx, n - offset) :    # 从上至下
                nums[i][n - offset] = count
                count += 1
            for i in range(n - offset, starty, -1) : # 从右至左
                nums[n - offset][i] = count
                count += 1
            for i in range(n - offset, startx, -1) : # 从下至上
                nums[i][starty] = count
                count += 1                
            startx += 1         # 更新起始点
            starty += 1

        if n % 2 != 0 :			# n为奇数时,填充中心点
            nums[mid][mid] = count 
        return nums

区间和

题目描述:给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。
重点:前缀和。
思想:遍历计算[0,i]的区间的和也就是前缀和, i ∈ [ 0 , l e n ( A r r a y ) − 1 ] i \in[0,len(Array)-1] i[0,len(Array)1]。缀和数组的每个元素存储的是原数组从起始位置到当前位置所有元素的累积和。在输入不同的区间的时候,只需要查询前缀和数组中相应的下标然后进行输出或者减法计算即可。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt();
        int[] vec = new int[n];
        int[] p = new int[n];

        int presum = 0;
        for (int i = 0; i < n; i++) {
            vec[i] = scanner.nextInt();
            presum += vec[i];
            p[i] = presum;
        }

        while (scanner.hasNextInt()) {
            int a = scanner.nextInt();
            int b = scanner.nextInt();

            int sum;
            if (a == 0) {
                sum = p[b];
            } else {
                sum = p[b] - p[a - 1];
            }
            System.out.println(sum);
        }

        scanner.close();
    }
}


import sys
input = sys.stdin.read

def main():
    data = input().split()
    index = 0
    n = int(data[index])
    index += 1
    vec = []
    for i in range(n):
        vec.append(int(data[index + i]))
    index += n

    p = [0] * n
    presum = 0
    for i in range(n):
        presum += vec[i]
        p[i] = presum

    results = []
    while index < len(data):
        a = int(data[index])
        b = int(data[index + 1])
        index += 2

        if a == 0:
            sum_value = p[b]
        else:
            sum_value = p[b] - p[a - 1]

        results.append(sum_value)

    for result in results:
        print(result)

if __name__ == "__main__":
    main()

开发商购买土地

重点:前缀和。

数组总结

关键:区间定义(循环不变量)和双指针。
基础:数组定义,存储。

相关的题目、视频和文章

  1. https://leetcode.cn/problems/minimum-size-subarray-sum/
  2. https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
  3. https://www.bilibili.com/video/BV1tZ4y1q7XE/
  4. https://leetcode.cn/problems/spiral-matrix-ii/
  5. https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html
  6. https://www.bilibili.com/video/BV1SL4y1N7mV/
  7. https://www.programmercarl.com/kamacoder/0058.%E5%8C%BA%E9%97%B4%E5%92%8C.html
  8. https://www.programmercarl.com/kamacoder/0044.%E5%BC%80%E5%8F%91%E5%95%86%E8%B4%AD%E4%B9%B0%E5%9C%9F%E5%9C%B0.html
  9. https://programmercarl.com/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93%E7%AF%87.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值