Java LeetCode篇-深入了解关于数组的经典解法

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍
 

 

 

文章目录

        1.0 轮转数组

        1.1 使用移位的方式

        1.2 使用三次数组逆转法

        2.0 消失的数字

        2.1 使用相减法

        2.2 使用异或的方式

        3.0 合并两个有序数组

        3.1 使用三指针方式

        3.2 使用合并排序方式

        4.0 删除有序数组中的重复项

        4.1 使用双指针方式

        5.0 移除元素

        5.1 使用双指针方式

        6.0 杨辉三角

        6.1 使用二维数组的方式


 

        1.0 轮转数组

题目:

        给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

        1.1 使用移位的方式

        先创建一个新的数组来记录需要进行右轮转的元素,然后将数组前面剩余的元素进行遍历 "移" 到后面,即覆盖。如例题1:先将 [5,6,7] 这 k 个元素使用新的数组来暂时存放,接着将 [1,2,3,4] 从后往前遍历,即将 4 移到原来 7 的位置,3 移到 原来 6 的位置,2 移到原来 5 的位置......即  nums[nums.length - i ]  = nums[ nums.length - k - i ]  i  从 1 开始直到 i == nums.length - k 时,则结束循环。最后,将需要轮转的元素进行数组 temp[] 下标一个个对应赋值到 nums[] 数组中即可。

代码如下:

    public static void rotate(int[] nums,int k) {
        if(nums.length == 1 || nums.length == 0) {
            return;
        }
        k %= nums.length;
        int[] temp = new int[k];
        System.arraycopy(nums,nums.length - k, temp, 0,k);
        System.arraycopy(nums,0,nums,k,nums.length - k);
        for(int i = 0;i < temp.length ; i++) {
            nums[i] = temp[i];
        }
    }

       这里使用了相关的 API ,总体上来说思路是一样的。一般来说,这种算法时间复杂度会较高。        

        1.2 使用三次数组逆转法

        使用三次逆转法,让数组旋转k次     

                        1. 整体逆置

                        2. 逆转子数组[0, k - 1]

                        3. 逆转子数组[k, size - 1]

代码如下:

    public static void fun(int[] arr, int k) {
        k %= arr.length;
        rotate(arr,0,arr.length - 1);
        rotate(arr,0,k-1);
        rotate(arr,k, arr.length-1);
    }
    public static void rotate(int[] arr,int left, int right) {
        while (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
    }

流程图如下:

        

        2.0 消失的数字

题目:

        数组 nums 包含从 到 的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在 O(n) 时间内完成吗?

示例 1:

输入:[3,0,1]
输出:2

示例 2:

输入:[9,6,4,2,3,5,7,0,1]
输出:8

       2.1 使用相减法

        定义 int sum ,然后遍历 0 到 n 的所有整数都加起来,接着再跟将 nums 的所以数字加起来进行比较两者相减即可得出 nums 数组中 "消失的数字" 。如例题:numsSum = 3 + 0 + 1 , nSum = 0 + 1 + 2 + 3,再接着 nSum - numsSum == 2 ,两者相减即可得到消失的数字为: 2 。

代码如下:

    public static int disappearing1(int[] arr) {
        int sum1 = 0;
        int sum2 = 0;
        for (int i = 0; i < arr.length; i++) {
            sum1 += i;
            sum2 += arr[i];
        }
        return (sum1 += arr.length) - sum2;
    }

        缺陷:如果数组中元素比较多,相加完成之后容易溢出。

       2.2 使用异或的方式

        采用异或的方式解决,因为两个相同的数字异或的结果是 0,因此:将 0~N 之间的数字,与数组中的每个数字异或,最终的结果就是丢失的数字。

代码如下:

    public static int disappearing(int[] arr) {

        int data = 0;
        for (int i = 0; i < arr.length; i++) {
            data ^= arr[i];
            data ^= i;
        }
        data ^= arr.length;
        return data;
    }

        分析:可以将将其理解为 “消消乐” ,即若两个数相同就抵消为 0 ,那么现在目前有两个袋子,一个袋子装满了 0 到 n 张卡片,其中每一种只有一片,也就是说,该袋子里面就有 n + 1 张卡片,在另一个袋子里面装有 0 到 n 张中缺少了一张卡片,即该袋子中有 n 张卡片,接着进行每一次将分别从两个袋子拿出不同的卡片进行对比,如果相同的话则抵消掉了,不相同的话,得保存起来。就这样一直对比下去,最终会发现留下来的就是另一个袋子所缺少的卡片了。

        3.0 合并两个有序数组

        给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

        3.1 使用三指针方式

        定义三个指针分别为:i 指向 nums1 中的最后一个有效元素j 指向 nums2 中最后一个有效元素k 指向 nums1 中最后一个索引位置。接着 nums[i] 与 nums[j] 进行比较大小,得出较大的元素就放到 nums[k] 中,以此类推,直到 i < 0 或者 j < 0 时,则循环停止。最后来判断,若 i > 0 ,本来剩余的元素就在 nums1 中,则不用再继续下去了,任务结束了;若 j > 0 ,需要将 nums2 中的元素进行遍历拷贝到 nums1 中

代码如下:

public void merge(int[] nums1, int m, int[] nums2, int n) {
        int k = nums1.length - 1;
        int i = m - 1;
        int j = n - 1;
        while(i >= 0 && j >= 0) {
            if(nums1[i] > nums2[j]) {
                nums1[k] = nums1[i];
                k--;
                i--;
            }else if(nums1[i] <= nums2[j]) {
                nums1[k] = nums2[j];
                k--;
                j--;
            }
        }

        if(j >= 0) {
            System.arraycopy(nums2,0,nums1,0,j+1);

        }

    }

        3.2 使用合并排序方式

        这个思路很简单,可以直接将 nums2 中的元素拷贝到 nums1 中,然后直接排序即可。这里就不过多赘述了。

        4.0 删除有序数组中的重复项

题目:

        给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2,并且原数组 nums 的前两个元素被修改为 1, 2不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。不需要考虑数组中超出新长度后面的元素。

        4.1 使用双指针方式

        先定义两个指针分别指向,一个指针: i = 0 ,一开始时指向数组中第一个元素另一个指针:j = 1。分两种情况来解决,第一种情况是,当 nums[i] == nums[j] 时,继续让 j 走下去,直到 j == nums.length 时,则结束循环;第二种情况是,当 nums[i] != nums[j] 时,让 nums[i + 1] = nums[j] ,i++,j++ ,同样直到 j == nums.length 时,则结束循环。最后返回 i+1 即可。

代码如下:

    public int removeDuplicates(int[] nums) {
        int i = 0;
        int j = i + 1;
        while (j < nums.length) {
            if (nums[i] == nums[j]) {
                j++;
            } else if (nums[i] != nums[j]) {
                nums[i+1] = nums[j];
                i++;
                j++;
            }
        }
        return i + 1;
    
    }

        5.0 移除元素

题目:

        给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

        不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,3,0,4]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

        5.1 使用双指针方式

        先定义两个指针,对于 left 这个指针来说,一开始指向数组下标为 0 对于 right 这个指针来说,一开始指向数组下标也为 0 处,然后 rigth 一直 right++ 自加,在这个过程中,需要先判断,若 nums[right]  != val 时,则需要将这个值拷贝到 nums[left] 中 ,left++right++ ;若 nums[right] == val 时,right++ 即可,直到 right == nums.length 时,则结束循环。

代码如下:

    public int removeElement(int[] nums, int val) {
        int n = nums.length;
        int left = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] != val) {
                nums[left] = nums[i];
                left++;
            }
        }
        return left;
    
    }

       

        6.0 杨辉三角

题目:

        给定一个非负整数 numRows生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

        

示例 1:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例 2:

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

        6.1 使用二维数组的方式

        可以把这个问题看成是一个二维数组,外层循环为 k 行数(层数),内层为 l 列数。当 l == 0 或者 k == l 时,该二维数组中存放的是 1 ;其他情况则为当前的数值为:上一层行数同一列的 data1 + 上一层行数少一列的 data2 。

 代码如下:

    public List<List<Integer>> generate(int numRows) {
      
        
        List<List<Integer>> i = new ArrayList<>();
        for (int k = 0; k < numRows; k++) {
            List<Integer> j = new ArrayList<>();
            for (int l = 0; l <= k ; l++) {
                if ( l == 0 || k == l) {
                    j.add(1);
                } else {
                    j.add(i.get(k-1).get(l) + i.get(k-1).get(l-1));
                }
            }
            i.add(j);
        }
         return i;


    }

        需要注意的是,实现集合来实现,而不是数组。

需要了解相关集合的内容可以点击该链接:进阶JAVA篇-深入了解 List 系列集合-CSDN博客

 

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

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

相关文章

浅谈UML的概念和模型之UML九种图

1、用例图&#xff08;use case diagrams&#xff09; 【概念】描述用户需求&#xff0c;从用户的角度描述系统的功能 【描述方式】椭圆表示某个用例&#xff1b;人形符号表示角色 【目的】帮组开发团队以一种可视化的方式理解系统的功能需求 【用例图】 2、静态图 类图&…

新形势下,2024年企业数字化转型该如何进行?

2023年已然接近尾声&#xff0c;各大企业都陆续开始了各种工作总结与来年规划。然而在大多传统企业中&#xff0c;负责数字化转型的部门人员则显得略微尴尬。 如何正确认识数字化、如何制定数字化年度目标以及如何快速体现数字化转型的价值&#xff0c;成为了数字化工作难以逾…

PlantUML语法(全)及使用教程-时序图

目录 1. 参与者1.1、参与者说明1.2、背景色1.3、参与者顺序 2. 消息和箭头2.1、 文本对其方式2.2、响应信息显示在箭头下面2.3、箭头设置2.4、修改箭头颜色2.5、对消息排序 3. 页面标题、眉角、页脚4. 分割页面5. 生命线6. 填充区设置7. 注释8. 移除脚注9. 组合信息9.1、alt/el…

传音荣获2023首届全国人工智能应用场景创新挑战赛“智能家居专项赛”三等奖

近日&#xff0c;中国人工智能学会与科技部新一代人工智能发展研究中心联合举办2023首届全国人工智能应用场景创新挑战赛&#xff08;2023 1st China’s Innovation Challenge on Artificial Intelligence Application Scene&#xff0c;以下简称CICAS 2023)&#xff0c;吸引了…

解决方案:新版WPS-右键粘贴值到可见单元格没有了

旧版WPS&#xff0c;右键就能出现 但是新版WPS不是在这里&#xff08;方法1&#xff09; 新版WPS&#xff08;方法2&#xff09; 视频详细教程链接&#xff1a;解决方案&#xff1a;新版WPS-右键粘贴值到可见单元格没有了 -- 筛选后复制公式粘贴为数值_哔哩哔哩_bilibili

Vue轻松入门,附带学习笔记和相关案例

目录 案例 一Vue基础 什么是Vue&#xff1f; 补充&#xff1a;mvvm框架 mvvm的组成 详解 Vue的使用方法 1.直接下载并引入 2.通过 CDN 使用 Vue 3.通过npm安装 4.使用Vue CLI创建项目 二插值表达式 什么是插值表达式&#xff1f; 插值表达式的缺点 解决方法 …

面对Spring 不支持java8的改变方法

接下来&#xff0c;就只有17与21了&#xff0c;JDK开发人员每隔半年&#xff0c;发布一个新的版本&#xff0c;但是新版本也只是维护一段时间&#xff08;一年/半年&#xff09;业务越小&#xff0c;升级越简单 1.如何创建Spring Boot项目,阿里云上去下载代码&#xff0c;然后使…

ESP32网络开发实例-Web页面控制直流电机

Web页面控制直流电机 文章目录 Web页面控制直流电机1、应用介绍2、软件准备3、硬件准备4、代码实现在这个 ESP32 Web务器应用中,我们将创建一个托管在 ESP32 上的网页,我们将使用该网页来控制使用 L298N 电机驱动器模块的直流电机的速度。 网页将包含一个 HTML 滑块,用于为直…

中低压MOSFET 2N7002KW 60V 300mA 双N通道 SOT-323封装

2N7002KW小电流双N通道MOSFET&#xff0c;电压60V电流300mA&#xff0c;采用SOT-323封装形式。超高密度电池设计&#xff0c;适用于极低的ros (on)&#xff0c;具有导通电阻和最大直流电流能力&#xff0c;ESD保护。可应用于笔记本中的电源管理&#xff0c;电池供电系统等产品应…

springBoot的实现原理;SpringBoot是什么;使用SpringBoot的核心功能;springBoot核心注解以及核心配置文件

文章目录 springBootspringBoot的实现原理什么是 Spring Boot&#xff1f;SpringBoot是什么为什么要使用springBootSpring Boot的核心功能Spring Boot 主要有如下优点&#xff1a; SpringBoot启动过程-流程Spring Boot 的核心注解是哪个&#xff1f;什么是 JavaConfig&#xff…

CMake语法解读 | Qt6需要用到

CMake 入门CMakeLists.txtmain.cpp编译示例cmake常用参数入门 Hello CMake CMake 是一个用于配置跨平台源代码项目应该如何配置的工具建立在给定的平台上。 ├── CMakeLists.txt # 希望运行的 CMake命令 ├── main.cpp # 带有main 的源文件 ├── include # 头文件目录 …

【全栈开发】Blitz.js与RedwoodJS

技术的不断发展是必然的。如果你仔细观察这片土地&#xff0c;你会注意到随着技术的成熟而出现的某些模式。特别是&#xff0c;开发人员一直在努力提高性能&#xff0c;简化开发过程&#xff0c;增强开发人员体验。 在本指南中&#xff0c;我们将分析两个帮助全栈应用程序世界…

【网安AIGC专题】46篇前沿代码大模型论文、24篇论文阅读笔记汇总

网安AIGC专题 写在最前面一些碎碎念课程简介 0、课程导论1、应用 - 代码生成2、应用 - 漏洞检测3、应用 - 程序修复4、应用 - 生成测试5、应用 - 其他6、模型介绍7、模型增强8、数据集9、模型安全 写在最前面 本文为邹德清教授的《网络安全专题》课堂笔记系列的文章&#xff0c…

nodejs+vue+elementui网上家电家用电器数码商城购物网站 多商家

基于vue.js的恒捷网上家电商城系统根据实际情况分为前后台两部分&#xff0c;前台部分主要是让用户购物使用的&#xff0c;包括用户的注册登录&#xff0c;查看公告&#xff0c;查看和搜索商品信息&#xff0c;根据分类定位不同类型的商品&#xff0c;将喜欢的商品加入购物车&a…

c语言:有关内存函数的模拟实现

memcpy函数&#xff1a; 功能&#xff1a; 复制任意类型的数据&#xff0c;存储到某一数组中。 代码模拟实现功能&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include <stdio.h> #include<assert.h> memcpy…

初识Spring (Spring 核心与设计思想)

文章目录 什么是 Spring什么是容器什么是 IoC理解 Spring IoCDI 概念 什么是 Spring Spring 官网 官方是这样说的: Spring 让每个人都能更快、更轻松、更安全地进行 Java 编程。春天的 专注于速度、简单性和生产力使其成为全球最受欢迎Java 框架。 我们通常所说的 Spring 指的…

避免手机无节制使用

手机使用情况分析 使用时间 我挑选了11月份某一周的统计数据&#xff0c;可以看到&#xff0c;我的日均手机手机时间达到了惊人的8个小时&#xff0c;每周总共余约57小时。 按照使用软件的类型来分类&#xff0c;其中约%50用于娱乐&#xff0c;主要使用软件为&#xff1a;哔哩…

Mac 搭建本地服务器

文章目录 1 启动服务器2 服务器目录3 手机访问服务器3.1 手机和电脑连上同一个局域网( 或WIFI)3.2 找到电脑的ip地址 如下图所示3.3 手机打开 http://192.168.10.5/1.txt 4 关闭服务器5 参考文章 1 启动服务器 sudo apachectl start启动后访问 http://localhost/ 如下图所示即…

Java第二十章 ——多线程

本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 在这之前&#xff0c;首先让我们来了解下在操作系统中进程和线程的区别&#xff1a;   进程&#xff1a;每个进程都有独立的代码和数据空间&#xff08;进程上下文…

SQL Server:流程控制语言详解

文章目录 一、批处理、脚本和变量局部变量和全局变量1、局部变量2、全局变量 二、顺序、分支和循环结构语句1、程序注释语句2、BEGIN┅END语句块3、IF┅ELSE语句4、CASE语句5、WHILE语句6、BREAK和CONTINUE语句BREAK语句CONTINUE语句 三、程序返回、屏幕显示等语句1、RETURN语句…