LeetCode_Day2 | 有意思的数组滑动窗口及螺旋矩阵

news2024/11/26 21:18:03

LeetCode_数组

  • 977.有序数组的平方
    • 1.题目描述
    • 2.暴力法
    • 3. 双指针法
  • 209.长度最小的子数组
    • 1.题目描述
    • 2.暴力法
    • 3.滑动窗口(双指针法)
  • 59.螺旋矩阵
    • 1.题目描述
    • 2. 螺旋矩阵解法

977.有序数组的平方

1.题目描述

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

详情LeetCode题链接: https://leetcode.cn/problems/squares-of-a-sorted-array/

2.暴力法

暴力法:最直观的想法,莫过于:每个数平方之后,排个序。

代码逻辑:

/**
     *思路:暴力法
     *     依次遍历数组,分别获取每个下标的值进行平方后,将平方后的值赋值到新数组内,并比较大小进行排序
     *时间复杂度:O(nlog n),其中n是数组nums 的长度。
     *空间复杂度:O(log n)。除了存储答案的数组以外,我们需要O(logn)的栈空间进行排序。
     */
    public int[] sortedSquares(int[] nums) {
        int[] newArray = new int[nums.length];  
        for (int i = 0; i < nums.length; i++){
            newArray[i] = nums[i] * nums[i];
        }
        Arrays.sort(newArray);
        return newArray;
    }

3. 双指针法

思路: 还是利用day1的双指针思想。

对于此题来说,数组其实是有序的, 只不过负数平方之后可能成为最大数了。

那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。

此时可以考虑双指针法了,i指向起始位置,j指向终止位置。

定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。

如果A[i] * A[i] < A[j] * A[j] 那么result[k–] = A[j] * A[j]; 。

如果A[i] * A[i] >= A[j] * A[j] 那么result[k–] = A[i] * A[i]。

代码实现逻辑:

 /**
     *思路:双指针法
     *     因为数组是有序的,由于负数的平方也是很大的数,所以此数组平方后数的大小是从两边向中间越来越小的。
     *     因此采用双指针法,i指向起始位置,j指向终止位置。
     *     定义一个新数组newArray,和nums数组一样的大小,让k指向newArray数组终止位置。
     *     如果nums[left] * nums[left] < nums[right] * nums[right] 那么newArray[newArrayIndex--] = nums[right] * nums[right]。
     *     如果nums[left] * nums[left] >= nums[right] * nums[right] 那么newArray[newArrayIndex--] = nums[left] * nums[left]。
     *时间复杂度:O(n),其中n是数组nums 的长度。
     *空间复杂度:O(1),除了存储答案的数组以外,我们只需要维护常量空间.
     */
    public int[] sortedSquares(int[] nums) {
        int right = nums.length - 1;
        int left = 0;
        int[] newArray = new int[nums.length];
        int newArrayIndex = nums.length - 1;
        while (left <= right) {
            if (nums[left] * nums[left] < nums[right] * nums[right]){
                newArray[newArrayIndex--] = nums[right] * nums[right--];
            }else {
                 newArray[newArrayIndex--] = nums[left] * nums[left++];
            }
        }
        return newArray;
    }

209.长度最小的子数组

1.题目描述

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

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

输入:target = 4, nums = [1,4,4]
输出:1

2.暴力法

不推荐此写法,超出LeetCode运行限制

思路:
暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

代码实现逻辑:

 /**
     *思路:暴力法
     *     利用双指针思想,暴力法遍历数组;初始化子数组的长度为无穷大。
     *     第一个for循环是子数组开始的位置,第二个for循环子数组结束的位置,当子数组内数值的和大于等于target时,将此时子数组的长度更新到初始的子数组长度。
     *     直至第一个for循环遍历结束为止。
     * 时间复杂度O(n^2)
     * 空间复杂度O(1)
     */
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        if (n == 0){
            return 0;
        }
        int ans = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++){
            int sum = 0;
            for (int j = i; j < n; j++){
                sum += nums[j];
                if (sum >= target){
                    ans = Math.min(ans,j-i+1);
                    break;
                }
            }
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }

3.滑动窗口(双指针法)

思路:
所谓滑动窗口,就是用一个for循环来不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。

  1. 思考问题1: 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置?

    假设用一个for循环来表示滑动窗口起始位置的话,剩余遍历的终止位置难免再陷入暴力法中了。

    所以只用一个for循环,那么循环的索引一定表示 滑动窗口的终止位置

  2. 思考问题2: 滑动窗口的起始位置如何移动?

    如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

  3. 思考问题3: 窗口内是什么?

    窗口内是 满足其和 ≥ s 的长度最小的 连续 子数组。

代码实现:

/**
     *思路:滑动窗口(双指针法)
     *     所谓滑动窗口即不断的调节子序列的起始和终止位置,从而得出我们要想的结果。
     *     窗口内是 满足其和 ≥ s 的长度最小的 连续 子数组。
     *     只用一个for循环,循环的索引用来表示滑块的终止位置。
     * 滑动窗口的起始位置如何移动则是重点:
     *    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是
     *    该缩小了)。
     *    窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的
     *    索引。
     * 相比暴力法:滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列
     *            的起始位置。从而将O(n^2)暴力解法降为O(n)。
     * 时间复杂度O(n)
     * 空间复杂度O(1)
     */
    public int minSubArrayLen(int target, int[] nums) {
       int sum = 0; //滑动窗口的数值之和
       int left = 0; //滑动窗口的起始位置
       int result = Integer.MAX_VALUE;
       for (int right = 0; right < nums.length; right++){
           sum += nums[right];
           //动态的调节窗口的起始位置
           // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
           while (sum >= target){
               result = Math.min(result,right-left+1);//right-left+1为子序列的长度
               sum -= nums[left++];// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
           }
       }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
       return result == Integer.MAX_VALUE ? 0 : result; 
    }

时间复杂度O(n)的理解:
不要以为for里放一个while就以为是O(n^2),主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)

59.螺旋矩阵

1.题目描述

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

示例:
在这里插入图片描述
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

输入:n = 1
输出:[[1]]

LeetCode题目详情链接:https://leetcode.cn/problems/spiral-matrix-ii/

2. 螺旋矩阵解法

1. 思路

根据螺旋矩阵特点,模拟画螺旋矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上
    由外向内一圈一圈这么画下去。

例举当n=3,n=4,n=5…时的螺旋矩阵,如下图:
请添加图片描述

请添加图片描述
请添加图片描述填充螺旋矩阵需要确定的边界:

  • 根据模拟螺旋矩阵的画法,需要确定随n的增大需循环几圈(即确定while的边界条件,转n/2圈,奇数时需要处理最后一个数字)
  • 遍历边填充元素时,需要遵循循环不变量原则(LeetCode_Day1中有示例题目),要么都是左闭右闭,要么都是左闭右开。

2. 代码实现:

/**
     * 思路:根据螺旋矩阵特点,模拟画螺旋矩阵的过程:
     *      填充上行从左到右,填充右列从上到下,填充下行从右到左,填充左列从下到上,即遍历了一圈。
     *      当n = 2时,需要按照上边遍历1圈;n=3时遍历1圈,n=4遍历...n=5....
     *      所以填充二维矩阵时,首先确定边界:即转几圈(转n/2圈,奇数时需要处理最后一个数字),和遍历时坚持循环不变量原则(即开闭区间需一致)。
     * 时间复杂度:O(n^2)
     * 空间复杂度:
     */
    public int[][] generateMatrix(int n) {
        int loop = 0;//控制循环次数
        int[][] res = new int[n][n];//初始化需要输出的结果数组
        int start = 0; //每次循环的开始位置下标 [start][start]
        int count = 1; //用于填充数字
        int i,j;
        while (loop++ < n/2){
            // 模拟上侧从左到右,左闭右开
            for (j = start; j < n - loop; j++){
                res[start][j] = count++; 
            }
            //模拟右侧从上到下,左闭右开
            for (i = start; i < n - loop; i++){
                res[i][j] = count++;
            }
            //模拟下侧从右到左,左闭右开
            for (;j > start; j--){
                res[i][j] = count++;
            }
            //模拟左侧从下到上,左闭右开
            for (;i > start; i--){
                res[i][j] = count++;
            }
            start ++;
        }
        if (n % 2 == 1){//如果n为基数,需要处理最后一个数字
            res[start][start] = count++;
        }
        return res;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/525166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决IDEA中集成Tomcat日志出现的乱码问题

解决IDEA中集成Tomcat日志出现的乱码问题 下面的方式可以解决的是解决的是idea中出现的控制台&#xff0c;Localhost日志以及Catalina日志乱码的问题 1.出现的乱码问题 你是不是也是遇到了这种的乱码的情况呢&#xff1f; 2.解决方法 1.打开conf文件夹。 2.设置输出的日志的编…

【小沐学Python】Python实现在线英语翻译功能

文章目录 1、简介2、在线翻译接口2.1 Google Translate API2.2 Microsoft Translator API2.2.1 开发简介2.2.2 开发费用2.2.3 开发API 2.3 百度翻译开放平台 API2.3.1 开发简介2.3.2 开发费用2.3.3 开发API 2.4 Tencent AI 开放平台的翻译 API2.4.1 开发简介2.4.2 开发API 2.5 …

人工智能基础部分16-神经网络与GPU加速训练

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能基础部分15-神经网络与GPU加速训练&#xff0c;在深度学习领域&#xff0c;神经网络已经成为了一种流行的、表现优秀的技术。然而&#xff0c;随着神经网络的规模越来越大&#xff0c;训练神经网络所需的时…

Kafka Connect JNDI注入漏洞复现(CVE-2023-25194)

漏洞原理 Apache Kafka Connect中存在JNDI注入漏洞&#xff0c;当攻击者可访问Kafka Connect Worker&#xff0c;且可以创建或修改连接器时&#xff0c;通过设置sasl.jaas.config属性为com.sun.security.auth.module.JndiLoginModule&#xff0c;进而可导致JNDI注入&#xff0c…

数字设计小思 - 谈谈非理想时钟的时钟偏差

写在前面 本系列整理数字系统设计的相关知识体系架构&#xff0c;为了方便后续自己查阅与求职准备。在FPGA和ASIC设计中&#xff0c;时钟信号的好坏很大程度上影响了整个系统的稳定性&#xff0c;本文主要介绍了数字设计中的非理想时钟的偏差来源与影响。 &#xff08;本文长…

数据结构-排序-(直接插入、折半插入、希尔排序、冒泡、快速排序)

目录 一、直接插入排序 二、折半插入排序 三、希尔排序 四、冒泡排序 五、快速排序 *效率分析 一、直接插入排序 思想&#xff1a;每次将一个待排序的记录按其关键字大小插入到前面已经排好序中&#xff0c;直到全部记录插入完毕 保证稳定性 空间复杂度&#xff1a;O(1…

SpringBoot 基本介绍--依赖管理和自动配置--容器功能

目录 SpringBoot 基本介绍 官方文档 Spring Boot 是什么? SpringBoot 快速入门 需求/图解说明 完成步骤 创建MainApp.java SpringBoot 应用主程序 创建HelloController.java 控制器 运行MainApp.java 完成测试 快速入门小结 Spring SpringMVC SpringBoot 的关系 梳…

【论文阅读】RapSheet:端点检测和响应系统的战术来源分析(SP-2020)

Tactical Provenance Analysis for Endpoint Detection and Response Systems S&P-2022 伊利诺伊大学香槟分校 Hassan W U, Bates A, Marino D. Tactical provenance analysis for endpoint detection and response systems[C]//2020 IEEE Symposium on Security and Priva…

【YOLO系列】--YOLOv5网络结构超详细解读/总结

前言 官方源码仓库&#xff1a;GitHub - ultralytics/yolov5: YOLOv5 &#x1f680; in PyTorch > ONNX > CoreML > TFLite YOLOv5至今没有论文发表出来&#xff0c;YOLOv5项目的作者是Glenn Jocher并不是原作者Joseph Redmon。作者当时也有说准备在2021年的12月1号之…

linux pl320 mbox控制器驱动分析 - (1) pl320手册分析

linux pl320 mbox控制器驱动分析 1 pl320简介1.1 pl320用途1.2 pl320 IPCM 由以下部分组成&#xff1a;1.3 pl320 IPCM可配置的参数1.4 功能操作1.5 IPCM 操作流程1.6 Channel ID 2 Using mailboxes&#xff08;使用邮箱中断&#xff09;2.1 Defining source core2.2 Defining …

JNI中GetObjectArrayElement, GetStringUTFChars,ReleaseStringUTFChars函数讲解

文章目录 GetObjectArrayElement函数使用场景代码演示GetStringUTFChars 函数使用场景ReleaseStringUTFChars函数 GetObjectArrayElement函数 函数原型&#xff1a; jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index); Returns an element of a J…

STL容器之deque

文章目录 deque容器简介deque的操作 deque容器简介 deque是“double-ended queue”的缩写&#xff0c;和vector一样都是STL的容器 deque是双端数组&#xff0c;而vector是单端的deque在接口上和vector非常相似&#xff0c;在许多操作的地方都可以直接替换deque可以随机存取元…

C语言-【操作符二】

Hello&#xff0c;大家好&#xff0c;前面的文章里边介绍了算术、赋值以及移位操作符&#xff0c;这篇文章呢&#xff0c;就介绍一下C语言中的其他操作符吧&#xff5e; 目录 位操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用&#xff0c;函…

C++11多线程:windows临界区和Linux互斥锁、递归锁的区别与使用。

文章目录 前言一、windows临界区1.1 基本概念1.2 函数使用 二、使用步骤1.代码示例1 总结 前言 多线程windows临界区和Linux互斥锁 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、windows临界区 1.1 基本概念 Linux下有递归锁&#xff0c;递归锁…

着重讲解一下自动化测试框架的思想与构建策略,让你重新了解自动化测试框架

目录 序言&#xff1a; 一、简述自动化测试框架 二、自动化测试框架思想 三、构建自动化测试框架的策略 四、自动化测试框架的发展趋势 序言&#xff1a; 也许到现在大家对所谓的“自动化测试框架”仍然觉得是一种神秘的东西&#xff0c;仍然觉得其与各位很远&#xff1b;…

【JavaScript】ES6新特性(1)

1. let 声明变量 let 声明的变量只在 let 命令所在的代码块内有效 块级作用域 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…

08-04 中间件和平台运行期监控

缓存中间件的三大坑 缓存击穿 用户访问热点数据&#xff0c;并且缓存中没有热点数据&#xff0c;大量访问直接到DB&#xff0c;热点击穿采用Canal做数据异构方案&#xff0c;把数据库中的值全部放到缓存热点缓存策略&#xff1a;通过分析调用日志获取热点数据&#xff0c;放到…

PMP项目管理-[第十一章]风险管理

风险管理知识体系&#xff1a; 规划风险管理&#xff1a; 识别风险&#xff1a; 实施定性风险分析&#xff1a; 实施定量风险分析&#xff1a; 监督风险&#xff1a; 11.1 风险 定义&#xff1a;是一种不确定的事件或条件&#xff0c;一旦发生&#xff0c;就会对一个或多个项目…

Elasticsearch(二)

Clasticsearch&#xff08;二&#xff09; DSL查询语法 文档 文档&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html 常见查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0c;一般测试用。如&#xff1a…

eNSP模拟器下VRRP+MSTP实验配置

①&#xff1a;底层配置&#xff1a; vlan trunk 略 ②&#xff1a;MSTP配置&#xff1a; 所有交换机&#xff1a; stp region-configuration region-name aa revision-level 1 instance 1 vlan 2 to 3 instance 2 vlan 4 to 5 active region-configuration 核心1&…