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

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.mfbz.cn/a/19716.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

推荐6个我经常逛的“小网站”,嘿嘿嘿!!!

如今&#xff0c;全球互联网上已经有超过 17 亿个网站。除了全球那些主流网站被大家所熟知外&#xff0c;其实还有很多很多网站&#xff0c;被淹没在了互联网世界中。 每次发现优质的内容都会第一时间给大家分享出来&#xff0c;不管是软件&#xff0c;插件&#xff0c;脚本还…

为什么要做计划跟踪:没有计划,就没有控制

日常工作中&#xff0c;我们每天都被大量的信息和任务填满&#xff0c;常常由于任务繁冗复杂&#xff0c;让人陷入一种无所适从的状态。 我们经常会看到很多如何安排工作计划的教程&#xff0c;比如&#xff1a; 要把大的项目分解为小目标&#xff0c;小目目标再分解为日常任务…

【iOS】—— 实现WebSocket发送消息(SocketRocket第三方库的使用和解析)

文章目录 WebSocketWebSocket特点 SocketRocket导入头文件设置代理SRWebSocket的初始化和建立连接SRWebSocketDelegate 代理方法实现加上简单UI实现两个用户之间简单通信浅看了一点点源码&#xff08;理解的不深&#xff09; 偶然之间了解到了利用WebSocket实现后端和前端的相互…

获取两个日期间时长 (XX天XX时XX分)

使用场景&#xff1a; 发货日期与到货日期 计算运输时长 代码&#xff1a; private String getMinuteTime(String startTime, String endTime) {String minuteTime null;if (StrUtil.isNotBlank(startTime) && StrUtil.isNotBlank(endTime)) {long minute DateUti…

华为OD机试真题 Java 实现【猜字谜】【2023Q1 100分】

一、题目描述 小王设计了一人简单的清字谈游戏&#xff0c;游戏的迷面是一人错误的单词&#xff0c;比如nesw&#xff0c;玩家需要猜出谈底库中正确的单词。猜中的要求如 对于某个谜面和谜底单词&#xff0c;满足下面任一条件都表示猜中&#xff1a; 变换顺序以后一样的&…

寅家科技完成近亿元B1轮融资,加速高阶智能驾驶布局

近日&#xff0c;寅家科技宣布完成近亿元人民币B1轮融资&#xff0c;本轮融资由东方富海、深创投、深圳高新投联合投资&#xff0c;所募资金主要用于公司高阶智能驾驶技术产品的研发迭代&#xff0c;以及智能驾驶产品量产、海外市场开拓&#xff0c;从而进一步提升核心产品的市…

【重新定义matlab强大系列三】MATLAB清洗离群数据(查找、填充或删除离群值)

&#x1f517; 运行环境&#xff1a;matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

应届生如何在职场中提高竞争力?这些方法和策略不容错过!

当前就业形势严峻&#xff0c;对于即将步入职场的应届生来说&#xff0c;提高自己的竞争力显得尤为重要。那么&#xff0c;要如何提高自己的职场竞争力呢&#xff1f;本文将为你分享一些有效的方法和策略&#xff0c;帮助你在职场中获得更好的发展。 一、提高自身素质 职场中&…

关于ADC的笔记1

ADC&#xff0c;全称Anlog-to-Digital Converter&#xff0c;模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件&#xff0c;我们能通过ADC将外界的电压值读入我们的单片机中. 常见的ADC有两种 1.并联比较型&#xff1a; 它的优点是转换速度最快&#x…

VMware 产品下载汇总 2023 持续更新中

本站 VMware 产品下载汇总&#xff1a;vSphere、NSX、Tanzu、Aria、Cloud… 请访问原文链接&#xff1a;https://sysin.org/blog/vmware/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 本站提供的 VMware 软件全部为 “试用版…

数据分析04——Pandas简介/Series对象/DataFrame对象

1、Pandas简介&#xff1a; Pandas是基于NumPy开发的数据分析三大剑客之一&#xff0c;Python数据分析的核心库提供快速、灵活、明确的数据结构Series对象&#xff1a;一维数组结构&#xff0c;由index和value构成DataFrame对象&#xff1a;二维数组结构&#xff0c;由index、…

106.(cesium篇)cesium椎体旋转

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <html lang="en"> <

RT-Thread 5.0.1 qemu-virt64-aarch64 解决编译问题

前言 最近在最新的 RT-Thread 上搭建 bsp qemu-virt64-aarch64 的编译环境&#xff0c;发现较新的 gcc 交叉编译器编译失败了。 经过尝试较旧版本的 gcc 交叉编译工具链&#xff0c;终于编译通过了 下载 gcc 交叉编译工具链&#xff0c;这里推荐使用 arm 官方的 gcc 下载地址…

眼球追踪、HDR、VST,从代码挖掘Valve下一代VR头显

擅长爆料、挖掘线索的Brad Lynch&#xff0c;此前发布了Quest Pro等设备的线索文章引发关注。​近期&#xff0c;又公布一系列与“Valve Deckard”VR头显相关消息&#xff0c;比如支持眼球追踪、HDR、VST透视、Wi-Fi网络等等。在SteamVR 1.26.1测试版更新、Steam用户端、Gamesc…

掌控MySQL并发:深度解析锁机制与并发控制

前一篇MySQL读取的记录和我想象的不一致——事物隔离级别和MVCC 讲了事务在并发执行时可能引发的一致性问题的各种现象。一般分为下面3种情况&#xff1a; 读 - 读情况&#xff1a;并发事务相继读取相同的记录。读取操作本身不会对记录有任何影响&#xff0c;不会引起什么问题&…

基于matlab使用主动声纳系统进行水下目标检测

一、前言 此示例演示如何模拟具有两个目标的主动单基地声纳方案。声纳系统由各向同性投影仪阵列和单个水听器元件组成。投影仪阵列呈球形。反向散射信号由水听器接收。接收到的信号包括直接和多路径贡献。 二、水下环境 在浅水环境中&#xff0c;声源和目标之间存在多个传播路径…

探索深度学习中的计算图:PyTorch的动态图解析

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

MySQL的高级语句

一、SQL高级语句 1、 SELECT 显示表格中一个或数个栏位的所有资料 语法&#xff1a;SELECT "字段" FROM "表名"; select * from test1; select name from test1; select name,sex from test1;2、DISTINCT 不显示重复的内容 语法&#xff1a;SELECT D…

2023年主流的选择仍是Feign, http客户端Feign还能再战

&#x1f473;我亲爱的各位大佬们好&#x1f618;&#x1f618;&#x1f618; ♨️本篇文章记录的为 微服务组件之http客户端Feign 相关内容&#xff0c;适合在学Java的小白,帮助新手快速上手,也适合复习中&#xff0c;面试中的大佬&#x1f649;&#x1f649;&#x1f649;。 …

古典密码体制--代换和置换

一、介绍与分类 1.介绍&#xff1a; 古典密码时期一般认为是从古代到19世纪末,这个时期生产力水平低,加密、解密方法主要以纸、笔或简单的器械来实现,在这个时期提出和使用的密码称为古典密码。古典密码是密码学发展的初级阶段。尽管古典密码大都较简单,但由于其安全性差&…
最新文章