L28.【LeetCode笔记】移动零(三种解法)

news2025/1/8 0:45:43

目录

1.题目

2.向前覆盖法

分析

代码

提交结果

3.优解:双指针

代码

提交结果

4.其他不符合题意的方法:使用队列

代码

 提交结果


1.题目

https://leetcode.cn/problems/move-zeroes/description/

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

进阶:你能尽量减少完成的操作次数吗?

2.向前覆盖法

分析

设一指针ptr,从头到尾遍历数组,发现num[ptr]==0时,执行向前覆盖,尾部填充一个0,但如果只这样写会有问题!

例如测试数据[0,0,1,0]

移动一次后发现1前面的元素nums[ptr-1]==0,即没有完全移动好1,那么这种情况出现时ptr要--

写成下面这样可以吗?

        if (nums[ptr-1]==0)
            ptr--;

不行会有潜在的越界风险! ptr-1可能会<0,因此要写成

        if (ptr>=1&&nums[ptr-1]==0)
            ptr--;

代码

void moveZeroes(int* nums, int numsSize) 
{
    int ptr=0;
    while(ptr<=numsSize-1)
    {
        if (ptr>=1&&nums[ptr-1]==0)
            ptr--;
        if (0==nums[ptr])
        {   

            for (int i=ptr;i<numsSize-1;i++)
            {
                nums[i]=nums[i+1];
            }
            nums[numsSize-1]=0;
            numsSize--;
        }      
        ptr++;
    }
}

提交结果

3.优解:双指针

LeetCode官方题解的双指针有点不好理解,其实可以直接分类讨论指针所指向的值:设两个指针prev和cur,当初始prev==0,cur==1时(先排除数组元素只有一个的情况),它们指向元素的情况无非就四种

1.nums[prev]==0,nums[cur]==0

2.nums[prev]!=0,nums[cur]==0

3.nums[prev]!=0,nums[cur]!=0

4.nums[prev]==0,nums[cur]!=0

首先看4:这种情况最好处理,nums[prev]交换nums[cur]就能将0向后移动

剩下情况1,情况2,情况3都要遵循一个原则:想方设法转换为情况4

情况1:nums[prev]==0,nums[cur]==0 --转换--> nums[prev]==0,nums[cur]!=0 :cur++寻找nums[cur]!=0

情况2:nums[prev]!=0,nums[cur]==0 --转换--> nums[prev]==0,nums[cur]!=0 :prev和cur都++

情况3:nums[prev]!=0,nums[cur]!=0 --转换--> nums[prev]==0,nums[cur]!=0 :附近没有0,prev和cur都++

代码

void moveZeroes(int* nums, int numsSize) 
{
    if(numsSize==1)
        return;
    int prev=0;
    int cur=1;
    while (cur<numsSize)
    {
        if (nums[prev]==0&&nums[cur]!=0)
        {
            int tmp=nums[prev];
            nums[prev]=nums[cur];
            nums[cur]=tmp;
        }
        if (nums[prev]!=0&&nums[cur]!=0)
        {
            prev++;
        }
        if (nums[prev]!=0&&nums[cur]==0)
        {
            prev++;
        }
        cur++;
    }
}

提交结果

4.其他不符合题意的方法:使用队列

虽然使用队列并没有原地对数组操作,但可以锻炼对队列的使用(其实直接开辟一个临时数组就行)

思想:将非0数字依次入队,遍历完一遍数组后再依次出队,原数组末尾补0

有关队列的文章参见:98.【C语言】数据结构之队列

代码

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QueueInit(Queue* pq)
{
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
		pq->head = pq->tail = NULL;
		pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	
	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

void QueuePop(Queue* pq)
{
	QNode* next = pq->head->next;
	free(pq->head);
	pq->head = next;
	if (pq->head == NULL)
		pq->tail = NULL;
	pq->size--;
}

bool QueueEmpty(Queue* pq)
{
	return pq->size == 0;
}

QDataType QueueFront(Queue* pq)
{
	return pq->head->data;
}

void moveZeroes(int* nums, int numsSize) 
{
    Queue q;
    QueueInit(&q);
    for (int i=0;i<numsSize;i++)
    {
        if (nums[i]!=0)
        {
            QueuePush(&q,nums[i]);
        }
    }
    int j=0;
    while(!QueueEmpty(&q))
    {
        nums[j]=QueueFront(&q);
        QueuePop(&q);
        j++;
    }
    for (;j<numsSize;j++)
    {
        nums[j]=0;
    }
    QueueDestroy(&q);
}

 提交结果

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

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

相关文章

js逆向实战(1)-- 某☁️音乐下载

下载某云音乐源文件.mp4格式 首先随便点进一首歌&#xff0c;如图所示获取该音乐id&#xff0c;然后点击播放键&#xff0c;打开F12进行查询XHR 由此可知&#xff0c;实际请求网址是 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token「你的token」url需带…

深入了解 SSL/TLS 协议及其工作原理

深入了解 SSL/TLS 协议及其工作原理 一. 什么是 SSL/TLS?二. SSL/TLS 握手过程三. SSL/TLS 数据加密与传输四. 总结 点个免费的赞和关注&#xff0c;有错误的地方请指出&#xff0c;看个人主页有惊喜。 作者&#xff1a;神的孩子都在歌唱 一. 什么是 SSL/TLS? 安全套接层&am…

Java四大常用JSON解析性能对比:Hutool、Fastjson2、Gson与Jackson测试

1. 引言 JSON 是现代软件开发中常用的数据交换格式&#xff0c;尤其在微服务和前后端分离的架构中更是必不可少。 本文将对 Java 中四大主流 JSON 解析库——Hutool、Fastjson2、Gson 和 Jackson 进行性能测试和对比分析&#xff0c;通过实测 20 万条数据解析&#xff0c;揭示…

【整理集合大全】MySQL(4) 数据库增删改查SQL语句

查看数据库 show databases; 使用数据库 use 数据库名;创建数据库 CREATE DATABASE 数据库名;删除数据库 DROP DATABASE 数据库名;创建表 create table 表名(列名1 类型(长度) [约束],列名2 类型(长度) [约束],…… );长度区别 int类型带长度&#xff1a;不影响存取值&…

升级 Spring Boot 3 配置讲解 —— Spring Boot 3 核心源码专讲

学会这款 &#x1f525;全新设计的 Java 脚手架 &#xff0c;从此面试不再怕&#xff01; Spring Boot 3 是 Spring 生态中的重要里程碑&#xff0c;它不仅全面支持 Java 17&#xff0c;还引入了许多新特性&#xff0c;如对 GraalVM 原生镜像的支持、改进的性能优化以及更灵活的…

vue3中el-table实现多表头并表格合并行或列

1、el-table中添加事件 :span-method"genderSpanCity" <el-table :span-method"genderSpanCity":data"data.tableData":fit"true" table-layout"fixed" header-align"center" stripestyle"width:100%;he…

OpenGL —— 流媒体播放器 - ffmpeg解码rtsp流,opengl渲染yuv视频(附源码,glfw+glad)

效果 说明 FFMpeg和OpenGL作为两大技术巨头,分别在视频解码和图形渲染领域发挥着举足轻重的作用。本文将综合两者实战视频播放器,大概技术流程为:ffmpeg拉取rtsp协议视频流,并经过解码、尺寸格式转换为yuv420p后,使用opengl逐帧循环渲染该yuv实时视频。 核心源码 vertexSh…

Web安全扫盲

1、建立网络思维模型的必要 1 . 我们只有知道了通信原理&#xff0c; 才能够清楚的知道数据的交换过程。 2 . 我们只有知道了网络架构&#xff0c; 才能够清楚的、准确的寻找漏洞。 2、局域网的简单通信 局域网的简单通信&#xff08;数据链路层&#xff09; 一般局域网都通…

HTML 显示器纯色亮点检测工具

HTML 显示器纯色亮点检测工具 相关资源文件已经打包成html等文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Html相关程序案例&#xff0c;秉着开源精神的想法&#xff0c;望大家喜欢&#…

ARM发布Armv9.5架构:迈向更强性能与灵活性的新时代

2024年11月30日&#xff0c;ARM正式发布了其最新的Armv9.5架构&#xff0c;这是Arm技术发展的又一重要里程碑。从表中信息来看&#xff0c;Armv9.5架构的发布标志着该公司的架构系列在性能、灵活性和可扩展性方面取得了进一步突破。本次发布不仅是技术上的提升&#xff0c;更是…

被催更了,2025元旦源码继续免费送

“时间从来不会停下&#xff0c;它只会匆匆流逝。抓住每一刻&#xff0c;我们才不会辜负自己。” 联系作者免费领&#x1f496;源&#x1f496;码。 三联支持&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;亲爱的朋友们&#xff0c;感谢你…

【Rust自学】10.4. trait Pt.2:trait作为参数和返回类型、trait bound

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 说句题外话&#xff0c;写这篇的时间比写所有权还还花的久&#xff0c;trait是真的比较难理解的概念。 10.4.1. 把trait作为参数 继续以…

R机器学习:神经网络算法的理解与实操,实例解析

神经网络算法是一种模仿生物神经网络&#xff08;尤其是人脑&#xff09;结构和功能的算法。它由大量相互连接的节点&#xff08;称为神经元&#xff09;组成&#xff0c;这些神经元组织成层&#xff0c;通过传递信号来处理信息。神经网络算法在机器学习、人工智能等领域中扮演…

Java(day4)

二维数组 静态初始化 动态初始化 练习 public class test1 {public static void main(String[]args){int arr[][]{{22,66,44},{77,33,88},{25,45,65},{11,66,99}};int sum0;for(int i0;i<arr.length;i){int a0;for(int j0;j<arr[i].length;j){sumarr[i][j];aarr[i][j];…

element-plus大版本一样,但是小版本不一样导致页面出bug

npm 的版本 node的版本 npm的源这些都一样&#xff0c;但是效果不一样 发现是element的包版本不一样导致的 2.9.1与2.8.1的源是不一样的&#xff0c;导致页面出bug;

【Docker】安装registry本地镜像库,开启Https功能

下载镜像 docker pull registry:2 需要启动https功能&#xff0c;就要生成服务端的自签名的证书和私钥&#xff0c;以及在docker客户端安装这个经过签名的证书。 第一步&#xff1a;生成公私钥信息&#xff0c;第二步&#xff0c;制作证书签名申请文件&#xff0c; 第三步&…

单片机-LED点阵实验

要将第一个点点亮&#xff0c;则 1 脚接高电平 a 脚接低电平&#xff0c;则第一个点就亮了&#xff1b;如果要将第一行点亮&#xff0c;则第 1 脚要接高电平&#xff0c;而&#xff08;a、b、c、d、e、f、g、h &#xff09;这些引脚接低电平&#xff0c;那么第一行就会点亮&…

PDFMathTranslate: Star13.8k,一款基于AI的PDF文档全文双语翻译PDF文档全文双语翻译,保留格式神器,你应该需要它

嗨&#xff0c;大家好&#xff0c;我是小华同学&#xff0c;关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 PDFMathTranslate是一个开源项目&#xff0c;旨在为用户提供便捷的PDF科学论文翻译解决方案。它不仅能够翻译文本&#xff0c;还能保留公式、图表、目…

RockyLinux9配置静态ip地址教程

以往我们配置linux系统的ip地址是在 /etc/sysconfig/network-scripts/ifcfg-网卡名 配置文件中编辑的&#xff0c;详情请见 Rocky8.10配置网络和主机名教程_rocky8配置网络-CSDN博客 但是在RockyLinux9系统中弃用了以前的这种方式&#xff0c;改为了新的配置方式。下面我们介绍…

民宿酒店预订系统小程序+uniapp全开源+搭建教程

一.介绍 一.系统介绍 基于ThinkPHPuniappuView开发的多门店民宿酒店预订管理系统&#xff0c;快速部署属于自己民宿酒店的预订小程序&#xff0c;包含预订、退房、WIFI连接、吐槽、周边信息等功能。提供全部无加密源代码&#xff0c;支持私有化部署。 二.搭建环境 系统环境…