代码随想录—力扣算法题:977有序数组的平方.Java版(示例代码与导图详解)

news2024/11/29 2:34:00

版本说明

当前版本号[20230807]。

版本修改说明
20230807初版

文章目录

  • 版本说明
  • 977.有序数组的平方
    • 思路
      • 暴力排序
      • 双指针法
    • 两种方法的区别
  • 总结

977.有序数组的平方

力扣题目链接
更多内容可点击此处跳转到代码随想录,看原版文件

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

示例 1:

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

示例 2:

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

思路

暴力排序

最直观的想法,莫过于:每个数平方之后,排个序,美滋滋,代码如下:

class Solution {
    public int[] sortedSquares(int[] A) {
        for (int i = 0; i < A.length; i++) {
            A[i] *= A[i];
        }
        Arrays.sort(A);
        return A;
    }
}

这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlog n)。

双指针法

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

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

此时可以考虑双指针法了,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];

如下展示:

第一步,新建数组【前提:所输入的是非递减数列】

image-20230807170648453

第二步:左、右指针比较平方大小,发现左指针的数值大,于是把 25 放进结果里,同时结果的下标往左走,左指针往右走

image-20230807170742747

第三步,继续往下走,发现右指针的数值大,于是把 16 放进结果里,同时结果的下标往左走,右指针往左走

image-20230807170959679

最后一步,结果就出来了

image-20230807171103054

示例代码:

class Solution {
    public int[] sortedSquares(int[] nums) {
        int l = 0;
        int r = nums.length - 1;//定义两个指针left(l)和right(r),分别指向数组的开头和结尾。
        int[] res = new int[nums.length];//定义一个新的数组result(res),用于存储平方后的结果。
        int j = nums.length - 1;//指向数组的结尾
        while(l <= r){
            if(nums[l] * nums[l] > nums[r] * nums[r]){
                res[j--] = nums[l] * nums[l++];
            }else{
                res[j--] = nums[r] * nums[r--];
            }
        }
    //使用一个循环,当left小于等于right时,执行以下步骤:
    //比较left指向的元素的平方和right指向的元素的平方的大小。
    //如果left指向的元素的平方较大,将其放入结果数组result的末尾,并将left指针向右移动一位。
    //如果right指向的元素的平方较大或两者相等,将其放入结果数组result的末尾,并将right指针向左移动一位。
        return res;//返回结果数组result(res)
    }
}

此时的时间复杂度为O(n),相对于暴力排序的解法O(n + nlog n)还是提升不少的。

两种方法的区别

解决给定问题的暴力解法中,我们可以使用以下步骤:

  1. 遍历输入数组nums中的每个元素。
  2. 对每个元素进行平方操作,并将平方值放入一个新的数组中。
  3. 对新数组进行排序。
  4. 返回排序后的新数组。

这种方法的时间复杂度为O(nlogn),其中n是输入数组的长度。原因是我们使用了一个内置的排序算法对新数组进行排序。

而在使用双指针的方法中,我们利用输入数组已经按非递减顺序排序的特点,通过双指针从两端向中间移动的方式来解决问题。具体步骤如下:

  1. 定义两个指针leftright,分别指向输入数组nums的开头和结尾。

  2. 定义一个新的数组result,用于存储平方后的结果。

  3. 使用一个index指针,从结果数组result的末尾开始填充元素。

  4. 使用一个循环,当left小于等于right时,执行以下步骤:

    • 比较left指向的元素的平方和right指向的元素的平方的大小。
    • 如果left指向的元素的平方较大,将其放入结果数组result的末尾,并将left指针向右移动一位。
    • 如果right指向的元素的平方较大或两者相等,将其放入结果数组result的末尾,并将right指针向左移动一位。
    • index指针向前移动一位。
  5. 返回结果数组result

    ​ 这种方法的时间复杂度为O(n),其中n是输入数组的长度。因为我们只需要遍历一次输入数组,并利用双指针从两端向中间移动的方式。

​ 因此,使用双指针法可以在线性时间复杂度下解决该问题,而暴力解法则需要使用排序算法,时间复杂度较高。所以,双指针法是更高效的解决方案。

总结

​ 对于这个问题,我们可以使用双指针的方法来解决。由于输入的数组已经是按非递减顺序排序的,**我们可以使用两个指针分别指向数组的开头和结尾,比较两个指针指向的元素的平方大小,然后将较大的平方值放入结果数组的末尾,并将相应的指针向中间移动。**重复这个过程直到两个指针相遇。

​ 通过比较每个元素的平方值的大小,将较大的值放入结果数组,并不断向中间移动指针,最终得到按非递减顺序排序的每个数字的平方组成的新数组。

​ 我们也可以写一个测试方法,输入一个非递减顺序排序的数组,来验证代码的正确性。

测试代码:

package shuzhu;

public class Day03
{
    public static int[] sortedSquares(int[] nums) {
        int l = 0;
        int r =nums.length - 1;
        int[] res = new int[nums.length];
        int j = nums.length - 1;
        while(l <= r)
        {
            if(nums[l] * nums[l] >nums[r] * nums[r])
            {
                res[j] = nums[l] * nums[l];
                j--;
                l++;
            }
            else
            {
                res[j] = nums[r] * nums[r];
                j--;
                r--;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int[] nums ={-7, 2, 4, 5, 6};
        int[] res = sortedSquares(nums);
        for(int i = 0; i < res.length;i++)
        {
            System.out.print(res[i]+" ");
        }
    }
}

        int[] nums ={-7, 2, 4, 5, 6};
        int[] res = sortedSquares(nums);
        for(int i = 0; i < res.length;i++)
        {
            System.out.print(res[i]+" ");
        }
    }
}

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

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

相关文章

NodeJs执行Linux脚本

&#xff08;我们活着不能与草木同腐&#xff0c;不能醉生梦死&#xff0c;枉度人生&#xff0c;要有所作为。——方志敏&#xff09; 为什么需要使用NodeJs执行Linux脚本 linux的sh脚本命令编写复杂&#xff0c;在不熟悉linux交互式命令的情况下&#xff0c;使用高级编程语言…

Source Insight和Keil中文乱码

1、问题原因 由于Source Insight和Keil中的中文编码方式的不同&#xff0c;导致Keil中添加的中文注释在Source Insight中乱码&#xff1b;在Source Insight中添加的中文注释在Keil中乱码。所以需要统一两者的编码方式。 Source Insight默认编码方式为UTF-8&#xff0c;Keil中一…

SolidWorks二次开发系列入门100篇之98、99-分割、保存零件中的实体

从这四张图&#xff0c;看了来这个保存实体和分割图标是一样的&#xff0c;可能只是选项不一样&#xff0c;所以这里一起写了&#xff0c;不浪费时间。 经过了几个小时的研究&#xff0c;没搞定。大哭 CreateSaveBodyFeature这个没有api例子&#xff0c;2021上有例子&#xff…

从小白到大神之路之学习运维第75天-------Harbor企业镜像仓库部署

第四阶段 时 间&#xff1a;2023年8月7日 参加人&#xff1a;全班人员 内 容&#xff1a; Harbor企业镜像仓库部署 目录 一、案例概述 二、什么是 Harbor &#xff08;一&#xff09;Harbor 的优势 &#xff08;二&#xff09;Harbor 架构构成 &#xff08;三&…

C++动态规划经典试题解析之打家劫舍系列

1.前言 力扣上有几道与打家劫舍相关的题目,算是学习动态规划时常被提及的经典试题,很有代表性,常在因内大大小小的社区内看到众人对此类问题的讨论。 学习最好的方式便是归纳总结、借鉴消化,基于这个目的,本文对此类问题也做了讲解,在一些优秀思想的基础上添加了个人观…

自然语言处理[信息抽取]:MDERank关键词提取方法及其预训练模型----基于嵌入的无监督 KPE 方法 MDERank

NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等 专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型…

一百四十八、Kettle——Linux上安装的kettle8.2连接Hive3.1.2

一、目标 kettle8.2在Linux安装好后&#xff0c;需要与Hive3.1.2数据库建立连接 二、前提 &#xff08;一&#xff09;在Linux已经安装好kettle并可以启动kettle &#xff08;二&#xff09;版本&#xff1a;kettle8.2.0 Hive3.1.2 Hadoop3.1.3 &#xff08;三&#…

虹科分享 | 如何通过ntopng流量规则来监控网络流量

让我们假设您有一个网络&#xff0c;其中本地主机生成恒定数量的流量。你如何发现他们是否行为错误&#xff1f;碰巧&#xff0c;一些本地主机行为开始异常&#xff0c;与它们之前相比&#xff0c;有一个异常的流量(发送或接收)&#xff1a;您如何发现这些情况并通过警报报告它…

使用langchain与你自己的数据对话(五):聊天机器人

之前我已经完成了使用langchain与你自己的数据对话的前四篇博客&#xff0c;还没有阅读这四篇博客的朋友可以先阅读一下&#xff1a; 使用langchain与你自己的数据对话(一)&#xff1a;文档加载与切割使用langchain与你自己的数据对话(二)&#xff1a;向量存储与嵌入使用langc…

[Securinets CTF Quals 2023] Admin Service,ret2libc,One is enough

只作了3个pwn&#xff0c;第4个附件没下下来&#xff0c;第5个不会 Admin Service 这是个最简单的题&#xff0c;最后来弄出来。原来只是看过关于maps文件的&#xff0c;一直没什么印象。 题目一开始设置seccomp禁用execv等&#xff0c;看来是用ORW&#xff0c;然后建了个mm…

STM32 4G学习

硬件连接 ATK-IDM750C模块可直接与正点原子 MiniSTM32F103开发板板载的ATK模块接口&#xff08;ATK-MODULE&#xff09;进行连接。 功能说明 ATK-IDM750C是正点原子&#xff08;ALIENTEK&#xff09;团队开发的一款高性能4G Cat1 DTU产品&#xff0c;支持移动4G、联通4G和…

详细介绍golang中.()类型断言的使用方法

文章目录 一、什么是.()用法&#xff1f;二、.()的基本用法三、.()用法的高级应用3.1 nil类型的转换3.2 将函数作为参数传递 四、.()使用中的注意事项五、总结 Golang是一门非常流行的编程语言&#xff0c;在很多领域都有着广泛的应用。在开发过程中&#xff0c;很多时候我们需…

verxriscv中Fpu中的加法器add源码分析

一 加法器端口 case class AddInput() extends Bundle{val source = Source()val rs1, rs2 = FpuFloat(exponentSize = p.internalExponentSize, mantissaSize = p.internalMantissaSize+addExtraBits)val rd = p.rfAddress()val roundMode = FpuRoundMode()val format = p.wit…

华为harmonyos4.0鸿蒙4.0安装谷歌服务框架Play商店,解决从服务器检索信息时出错

8月4号华为手机发布了全新的harmonyos4.0鸿蒙4.0系统&#xff0c;很多人需要问还是不是支持谷歌服务框架&#xff1f;那么答案是肯定的&#xff0c;它和鸿蒙3是一样的&#xff0c;一样的操作&#xff0c;一样的支持安装谷歌服务框架&#xff0c;安装Google play商店。测试机型&…

【新】通达OA前台反序列化漏洞分析

0x01 前言 注&#xff1a;本文仅以安全研究为目的&#xff0c;分享对该漏洞的挖掘过程&#xff0c;文中涉及的所有漏洞均已报送给国家单位&#xff0c;请勿用做非法用途。 通达OA作为历史上出现漏洞较多的OA&#xff0c;在经过多轮的迭代之后已经很少前台的RCE漏洞了。一般来说…

python+requests+json 接口测试思路示例

实际项目中用python脚本实现接口测试的步骤&#xff1a; 1 发送请求&#xff0c;获取响应 》》2 提取响应里的数据&#xff0c;对数据进行必要的处理 》》3 断言响应数据是否与预期一致 以豆瓣接口为例&#xff0c;做一个简单的接口测试吧。使用到的知识涉及requests库&…

Vue3 第三节 计算属性,监视属性,生命周期

1.computed计算属性 2.watch监视函数 3.watchEffect函数 4.Vue的生命周期函数 一.computed计算属性 计算属性简写和完整写法 <template><h1>一个人的信息</h1>姓&#xff1a;<input type"text" v-model"person.firstName" />…

车载A2B总线AD2428主从模式调试问题汇总

一&#xff0c;简介 在实际A2B总线一主一从模式的调试过程中下载程序出现许多报错提示&#xff0c;本文将遇到的错误进行汇总记录&#xff0c;方便相关开发者进行参考。 二&#xff0c;错误现象 2.1 Cable Terminal Shorted to Ground 主机IIS&#xff08;TDM&#xff09;线…

Mir 2.14 正式发布,Ubuntu 使用的 Linux 显示服务器

Canonical 公司最近发布了 Mir 2.14&#xff0c;这是该项目的最新版本。 Mir 2.14 在 Wayland 方面通过 ext-session-lock-v1 协议增加了对屏幕锁定器 (screen lockers) 的支持&#xff0c;并最终支持 Wayland 拖放。此外还整合了渲染平台的实现&#xff0c;放弃了之前在 Raspb…

常见监控网络链路和网络设备的方法

网络监控主要包括网络链路监控和网络设备监控&#xff0c;通常系统运维人员会比较关注。 一、网络链路监控 网络链路监控主要包含三个部分&#xff0c;网络连通性、网络质量、网络流量。 连通性和质量的监控手段非常简单&#xff0c;就是在链路一侧部署探针&#xff0c;去探…