基础算法之双指针--Java实现(上)--LeetCode题解:移动零-复写零-快乐数-盛最多的水

news2024/11/20 20:40:58

这里是Thembefue 

今天讲解算法中较为经典的一个算法

本讲解主要通过题目来讲解以理解算法

讲解分为三部分:题目解析 => 算法讲解 => 编写代码

 移动零

        题目链接: 移动零

      题目解析

这题的题目意思还是比较好读懂的 就是将数组出现零的地方移到数组最后面,且数组数字的顺序不能改变,更不能创建新的数组来更改

        算法讲解

标题既然是双指针,那么这题肯定是双指针来解决了。

1. 我们先定义两个指针变量:dest和cur。

2. cur从左往右遍历数组。

3. 若是cur指向的元素为非零元素,则将dest和cur指向的元素交换。同时dest才向后移动

以上便是模拟此次过程的代码 

如果将上面的某一过程提取出来,会发现此时数组分为了三个区域

那么根据上述的算法讲解,就可以实现代码了 

        编写代码 

class Solution {
    public void moveZeroes(int[] nums) {
        // 双指针
        int dest = 0;
        int cur = 0;

        while (cur < nums.length) {
            if (nums[cur] != 0) {
                swap(nums, dest, cur);
                dest++;
            }
            cur++;
        }
    }

    public void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

复写零

        题目链接:复写零

      题目解析

这道题的意思就是将数组中的零元素复制一个到数组里,但是数组的长度不能改变,我们先根据异地操作来模拟一遍过程。

 

算法讲解 

以上便是异地双指针操作的全部过程,但是题目并不能创建额外的空间,所以我们必须使用双指针对原数组进行修改

如果单纯地从左向右修改的话,那么就会导致非零数字被覆盖的情况

所以我们采用从后往前复写

首先找到最后一个需要 “复写” 的元素

先判断 i 指针当前位置的值 => 若为0,则 j 指针往后移两步,否则移动一步。 

再判断此时 j指针是否走的数组最后一个元素。

最后让 i 指针往后移动一步。

找到最后一个复写的元素后,不能立刻复写。

此时可能会出现特殊情况,就是 j 指针可能指向的不是数组的最后一个元素,而是数组外的位置,这会导致数组越界。

所以还需额外判断 => 若确实出现这种情况,这应该先复写一次。

编写代码 

class Solution {
    public void duplicateZeros(int[] arr) {
        int cur = 0;
        int dest = -1;

        // 找到最后一个需要复写的元素
        while (true) {
            if (arr[cur] == 0) {
                dest += 2;
            } else {
                dest += 1;
            }
            if (dest >= arr.length - 1) {
                break;
            }
            cur++;
        }

        if (dest >= arr.length) {
            arr[dest - 1] = 0;
            dest -= 2;
            cur -= 1;
        }

        while (cur >= 0) {
            if (arr[cur] == 0) {
                arr[dest--] = arr[dest--] = 0;
            } else {
                arr[dest--] = arr[cur];
            }
            cur--;
        }
    }
}

快乐数

        题目链接:快乐数

      题目解析

这题的题目意思还是比较好懂的,所以我就不做过多解释了。 

有一个至关重要的点就是,如果这个数不是快乐数的话,它是会无限循环的,它不会一直增大,而是会成一个圈,也就永远不会到达1。

 

示例上的两种情况一一列举出来,可以看到,第二种所示情况成为一个环。 

算法讲解 

这题的核心思路便是快慢指针,即双指针的一种,快指针一次走多步(一般是走两步),慢指针一次走一步。

好比操场跑步,配速更快的同学一定会在某一个时间以不同的圈数到达配速更慢的同学的位置,此时两位同学相遇了。

利用这个规律,快慢指针若会相遇,则说明此时成环了,也就不是快乐数,否则为快乐数。

当然成环了也不一定不是快乐数,若遇到1,则会一直是1,当然这种情况其实就已经可以结束了。

编写代码

class Solution {
    public boolean isHappy(int n) {
        int slow = n, fast = getNext(n);
        while (slow != fast) {
            slow = getNext(slow);
            fast = getNext(getNext(fast));
        }
        return slow == 1;
    }
    
    private int getNext(int n) {
        int totalSum = 0;
        while (n > 0) {
            int d = n % 10;
            n = n / 10;
            totalSum += d * d;
        }
        return totalSum;
    }
}

盛最多水的容器

        题目链接:盛最多水的容器​​​​​​

      题目解析

这题的本质就是面积,但要求的是最大面积

任取两个数组下标,这两个数组的下标之间的距离构成宽

这两个下标所指向的元素,哪个元素更小,即构成高

算法讲解

众所周知,长方形的面积等于高乘宽。

有了这个定理,我们再看这题,利用单调性,再利用双指针就可以解决了。

我们定义两个指针,一个指向数组的头,另一个指向数组的尾。

这两个指针当然会向中间靠近,知道相遇,结束计算。

首先,我们要先知道的是,既然两个指针逐渐向中间靠近,那么该长方形的宽只会递减,不会出现增加的情况。

其次,就是如何递减了,同时递减?显然不可能。既然该长方形的高是由指针指向的元素且是两个指针的较小的值所构成的,所以,只需要让更小的元素向前或向后移动就好了。

编写代码 

class Solution {
    public int maxArea(int[] height) {
        int left = 0, right = height.length - 1, max = 0;

        while (left < right) {
            int tmp = (right - left) * Math.min(height[left], height[right]);
            max = Math.max(max, tmp);
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return max;
    }
}

好了,以上就是今天内容的全部讲解,如果有不懂的地方,随时私聊😘

我们下半部分见😁

 

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

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

相关文章

【SpringCloud】 统⼀服务⼊⼝-Gateway

统⼀服务⼊⼝-Gateway 1. ⽹关介绍1.1 问题1.2 什么是API⽹关1.3 常⻅⽹关实现ZuulSpring Cloud Gateway 2. 上手 1. ⽹关介绍 1.1 问题 前⾯的课程中, 我们通过Eureka, Nacos解决了服务注册, 服务发现的问题, 使⽤Spring Cloud LoadBalance解决了负载均衡的问题, 使⽤OpenFe…

使用 Seaborn 热图的 5 种方法(Python 教程)

如何计算 SHAP 特征贡献的概述 原文地址: https://mp.weixin.qq.com/s/nBb9oKlSzRW8w7widHJr6w 热图可以让你的数据变得生动。用途广泛且引人注目。在很多情况下,它们可以突出显示数据中的重要关系。具体来说,我们将讨论如何使用它们来可视化: 模型准确度的混淆矩阵时间序列…

如何从硬盘恢复丢失/删除的视频

您是否想知道是否可以恢复已删除的视频&#xff1f; 幸运的是&#xff0c;您可以使用奇客数据恢复从硬盘驱动器、SD 卡和 USB 闪存驱动器恢复已删除的视频文件。 你有没有遇到过这样的情况&#xff1a;当你随机删除文件以释放空间时&#xff0c;你不小心按下了一些重要视频的…

SysML案例-停车场

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>>

求职Leetcode题目(12)

1.只出现一次的数字 异或运算满足交换律 a⊕bb⊕a &#xff0c;即以上运算结果与 nums 的元素顺序无关。代码如下&#xff1a; class Solution {public int singleNumber(int[] nums) {int ans 0;for(int num:nums){ans^num;}return ans;} } 2.只出现一次的数字II 这是今天滴…

跳跃列表(Skip List)详解

什么是跳跃列表&#xff1f; 跳跃列表是一种概率性的数据结构&#xff0c;旨在提高链表的搜索、插入和删除效率。它通过在普通链表的基础上增加多个层次&#xff0c;以实现更快的访问速度。跳跃列表的设计灵感来源于跳跃图&#xff08;Skip Graph&#xff09;和多层索引的概念…

使用Materialize制作unity的贴图,Materialize的简单教程,Materialize学习日志

Materialize 官网下载地址&#xff1a;http://boundingboxsoftware.com/materialize/ github源码地址&#xff1a;https://github.com/BoundingBoxSoftware/Materialize 下载地址&#xff1a;http://boundingboxsoftware.com/materialize/getkey.php 下载后解压运行exe即可 …

带徒实训项目实战讲义分享:ApiFirst文档对比功能页面开发

亲爱的学员朋友&#xff0c;前面咱一起实现了入参列表对比的部分功能&#xff0c;本节在此基础上继续开发和重构代码&#xff0c;go&#xff01; 文章目录 已实现的功能实现API入参列表的增删对比合并参数列表杜绝内部变量暴露提取modifiedType枚举 已实现的功能 基于0.0.6和…

算术操作符/和*、while、for循环

上一次我们讲到float等浮点型的数据范围和数据类型长度&#xff0c;以及sizeof可以查看变量、表达式、数据类型的字节数即所占内存。 除法/和乘法* 我们继续用计算器这个例子来学习其他语法。先来看最初我们写成的代码&#xff1a; #include<stdio.h> int Add(int a, …

基于YOLOv4和DeepSORT的车牌识别与跟踪系统

1. 项目简介 本项目旨在开发一个基于深度学习的自动车牌识别&#xff08;Automatic License Plate Recognition, ALPR&#xff09;系统&#xff0c;以实现对车辆牌照的实时检测、识别和追踪。自动车牌识别技术广泛应用于智慧交通、停车管理、电子收费和执法监控等领域&#xf…

Golang | Leetcode Golang题解之第440题字典序的第K小数字

题目&#xff1a; 题解&#xff1a; func getSteps(cur, n int) (steps int) {first, last : cur, curfor first < n {steps min(last, n) - first 1first * 10last last*10 9}return }func findKthNumber(n, k int) int {cur : 1k--for k > 0 {steps : getSteps(cu…

c++11新特性-下

c11的线程库可以跨平台使用。 原子性操作库(atomic) 不需要对原子类型变量进行加锁解锁操作&#xff0c;线程能够对原子类型变量互斥的访问。 atmoic<T> t; // 声明一个类型为T的原子类型变量t 在C11中&#xff0c;原子类 型只能从其模板参数中进行构造&#xff0c;不…

【规控+slam】探索建图方案及代码分享

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言背景建图描述SLAM定位+感知数据标记构建地图自动探索建图规划方法一:手动遥控探索建图算法步骤方法二:手动给定目标点探索建图算法原理方法三:f…

VMware虚拟机连接公网,和WindTerm

一、项目名称 vmware虚拟机连接公网和windterm 二、项目背景 需求1&#xff1a;windows物理机&#xff0c;安装了vmware虚拟机&#xff0c;需要访问公网资源&#xff0c;比如云服务商的yum仓库&#xff0c;国内镜像加速站的容器镜像&#xff0c;http/https资源。 需求2&#xf…

Hive数仓操作(八)

一、Hive中的分桶表 1. 分桶表的概念 分桶表是Hive中一种用于提升查询效率的表类型。分桶指的是根据指定列的哈希值将数据划分到不同的文件&#xff08;桶&#xff09;中。 2. 分桶表的原理 哈希分桶&#xff1a;根据分桶列计算哈希值&#xff0c;对哈希值取模&#xff0c;将…

【漏洞复现】JeecgBoot 积木报表 queryFieldBySql sql注入漏洞

》》》产品描述《《《 积木报表&#xff0c;是一款免费的企业级Web报表工具&#xff0c;像搭建积木一样在线设计报表!功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等! 》》》漏洞描述《《《 JeecgBoot 积木报表 queryFieldBySq| 接口存在一个 SQL 注入漏洞&…

Web和UE5像素流送、通信教程

一、web端配置 首先打开Github地址&#xff1a;https://github.com/EpicGamesExt/PixelStreamingInfrastructure 找到自己虚幻引擎对应版本的项目并下载下来&#xff0c;我这里用的是5.3。 打开项目找到PixelStreamingInfrastructure-master > Frontend > implementat…

NodeJS下载、安装及环境配置教程,内容详实

文章目录 概述关于本文NodeJS介绍 安装步骤 概述 关于本文 本文讲解如何在Windows系统中安装NodeJS并配置相关环境。 NodeJS介绍 Node.js&#xff08;通常简称为Node&#xff09;是一个开源、跨平台的JavaScript运行时环境&#xff0c;它允许开发者在服务器端运行JavaScrip…

【PyTorch】图像分割

图像分割是什么 Image Segmentation 将图像每一个像素分类 图像分割分类 超像素分割&#xff1a;少量超像素代替大量像素&#xff0c;常用于图像预处理语义分割&#xff1a;逐像素分类&#xff0c;无法区分个体实例分割&#xff1a;对个体目标进行分割全景分割&#xff1a;…

Simulink仿真中get_param函数用法

目录 语法 说明 示例 获取模块参数值和模型参数值 获取根参数名称和值 获取模型参数名称和值 获取模块列表和参数值 使用模块句柄获取模块参数值 显示模型中所有模块的模块类型 获取封装参数、Simulink 对象、模块图或注释的选项列表 获取封装参数的计算值 get_para…