Leetcode 86. 分隔链表

给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。

示例:

输入: head = 1->4->3->2->5->2, x = 3

输出: 1->2->2->4->3->5

题目分析:本题让我们把原来的链表进行分隔,小于x的在前,大于等于x的在后。并且,元素之间还需要保持原有的相对顺序。在下面的图例中,我们可以看到原有元素的顺序。分隔完后,在原来索引位置5处的元素2依然排在索引位置为3处的元素2之后。640?wx_fmt=png

在思考这道题如何解的时候,我们先回忆一下我们在算法课中也接触过类似的partition方法,这种方法在quick sort(快速排序)中也出现过。快速排序采用分治的思想,通过某一分界值将数组分成左右两部分,将大于等于分界值的数据集中到右侧,将小于分界值的数据集中到左侧。然后分别对左侧右侧进行上述处理,直到每一侧都排好序,那么整体也就排好序了。我们看下面的这个例子,对原数组我们选择最后一个元素作为分界值,然后左侧都是小于70的元素,右侧都是大于70的元素。然后对于左侧和右侧,我们选择他们中的最后一个元素作为分界值继续进行划分,一直到最后每一侧都排好序(即这一侧只含有一个元素或者为空),该算法停止。该算法的时间复杂度为O(nlogn)。640?wx_fmt=png

对应的C++参考代码如下

int partition(vector<int> &input, int low, int high) {	int pivot = input[high];	int i = low - 1;	for (int j = low; j <= high - 1; j++) {	if (input[j] < pivot) {	++i;	swap(input[i], input[j]);	}	}	swap(input[i + 1], input[high]);	return i + 1;	
}	
void quickSort(vector<int> &input, int low, int high) {	if (low < high) {	int index = partition(input, low, high);	quickSort(input, 0, index - 1);	quickSort(input, index + 1, high);	}	
}

回到本题中,既然需要将链表分隔为两部分,那么我们可以设置两个dummy节点分别保存链表的一部分,dummy1作为小于x的节点的链表的头结点,dummy2作为大于等于x的节点的链表的头结点,如果当前节点的值小于x,我们就将当前节点放到dummy1链表的末尾。如果当前节点的值大于等于x,我们就将其插入dummy2链表的末尾。这样我们就将原链表划分成了两部分,并且保证了相对顺序。最后链接成的链表结果如下图显示,我们的算法时间复杂度为O(n)。下面分别给出不同语言的代码实现。640?wx_fmt=png

C++代码

ListNode* partition(ListNode* head, int x) {	if (head == NULL || head->next == NULL) return head;	ListNode* dummy1 = new ListNode(0);	ListNode* dummy2 = new ListNode(1);	ListNode *tail1 = dummy1, *tail2 = dummy2;	ListNode* curr = head;	while (curr != NULL) {	if (curr->val < x) {	tail1->next = curr;	tail1 = tail1->next;	} else {	tail2->next = curr;	tail2 = tail2->next;	}	curr = curr->next;	}	if (tail1 == NULL) return tail2;	if (tail2 == NULL) return tail1;	tail2->next = NULL;	tail1->next = dummy2->next;	return dummy1->next;	}

Java代码

public ListNode partition(ListNode head, int x) {	if (head == null || head.next == null) return head;	ListNode dummy1 = new ListNode(0);	ListNode dummy2 = new ListNode(0);	ListNode smallTail = dummy1, largeTail = dummy2;	ListNode curr = head;	while (curr != null) {	if (curr.val < x) {	smallTail.next = curr;	smallTail = smallTail.next;	} else {	largeTail.next = curr;	largeTail = largeTail.next;	}	curr = curr.next;	}	smallTail.next = dummy2.next;	largeTail.next = null;	return dummy1.next;	}

C#代码

 public ListNode Partition(ListNode head, int x) {	if (head == null || head.next == null)	{	return head;	}	ListNode dummy1 = new ListNode(0);	ListNode dummy2 = new ListNode(0);	ListNode smallTail = dummy1, largeTail = dummy2;	ListNode curr = head;	while (curr != null)	{	if (curr.val < x)	{	smallTail.next = curr;	smallTail = smallTail.next;	} else	{	largeTail.next = curr;	largeTail = largeTail.next;	}	curr = curr.next;	}	smallTail.next = dummy2.next;	largeTail.next = null;	return dummy1.next;	}

Golang代码

func partition(head *ListNode, x int) *ListNode {	if head == nil || head.Next == nil {	return head	}	dummy1 := new(ListNode)	dummy2 := new(ListNode)	smallTail := dummy1	largeTail := dummy2	curr := head	for curr != nil {	if curr.Val < x {	smallTail.Next = curr	smallTail = smallTail.Next	} else {	largeTail.Next = curr	largeTail = largeTail.Next	}	curr = curr.Next	}	smallTail.Next = dummy2.Next	largeTail.Next = nil	return dummy1.Next	
}

Python3代码

def partition(self, head: ListNode, x: int) -> ListNode:	if head == None or head.next == None:	return head	dummy1 = ListNode(0)	dummy2 = ListNode(0)	smallTail = dummy1	largeTail = dummy2	curr = head	while curr != None:	if curr.val < x:	smallTail.next = curr	smallTail = smallTail.next	else:	largeTail.next = curr	largeTail = largeTail.next	curr = curr.next	smallTail.next = dummy2.next	largeTail.next = None	return dummy1.next

由本题可见,一些经典的算法我们还是要学透吃透,这样在碰到类似问题或者问题变种的时候才能将经典算法应用过来,快速解决问题。

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

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

相关文章

深入理解 JVM Class文件格式(一)

** 一、JVM体系结构 ** ** 二、class格式文件概述 ** class文件是一种8位字节的二进制流文件&#xff0c; 各个数据项按顺序紧密的从前向后排列&#xff0c; 相邻的项之间没有间隙&#xff0c; 这样可以使得class文件非常紧凑&#xff0c; 体积轻巧&#xff0c; 可以被J…

深入理解 JVM Class文件格式(二)

** class文件中的特殊字符串 ** 特殊字符串是常量池中符号引用的一部分&#xff0c;包括三种&#xff1a; 类的全限定名&#xff0c; 字段和方法的描述符&#xff0c; 特殊方法的方法名。 下面我们就分别介绍这三种特殊字符串。 &#xff08;1&#xff09; 类的全限定名 在…

.NET框架之“小马过河”

.NET框架之“小马过河”有许多流行的 .NET框架&#xff0c;大家都觉得挺“重”&#xff0c;认为很麻烦&#xff0c;重量级&#xff0c;不如其它“轻量级”框架&#xff0c;从而不愿意使用。面对形形色色的框架发愁&#xff0c;笔者也曾发愁。但我发现只要敢于尝试&#xff0c;这…

深入理解 JVM Class文件格式(三)

** JVM常量池中各数据项类型详解 ** 关于常量池的大概内容&#xff0c; 已经在 深入理解 JVM Class文件格式&#xff08;一&#xff09; 中讲解过了&#xff0c; 这篇文章中还介绍了常量池中的11种数据类型。 本文的任务是详细讲解这11种数据类型&#xff0c; 深度剖析源文件…

深入理解 JVM Class文件格式(四)

&#xff08;3&#xff09;CONSTANT_Integer_info 一个常量池中的CONSTANT_Integer_info数据项, 可以看做是CONSTANT_Integer类型的一个实例。 它存储的是源文件中出现的int型数据的值。 同样&#xff0c; 作为常量池中的一种数据类型&#xff0c; 它的第一个字节也是一个tag值…

.Net Core中使用Quartz.Net Vue开即用的UI管理

Quartz.NETQuartz.Net 定制UI维护了常用作业添加、删除、修改、停止、启动功能&#xff0c;直接使用cron表达式设置作业执行间隔&#xff0c;有完整的日志记录。Quartz.NET是一个功能齐全的开源作业调度系统&#xff0c;可用于从最小的应用程序到大型企业系统。Quartz.NET是一个…

深入理解 JVM Class文件格式(五)

&#xff08;8&#xff09; CONSTANT_Class_info 常量池中的一个CONSTANT_Class_info&#xff0c; 可以看做是CONSTANT_Class数据类型的一个实例。 他是对类或者接口的符号引用。 它描述的可以是当前类型的信息&#xff0c; 也可以描述对当前类的引用&#xff0c; 还可以描述对…

混沌工程详细介绍——Netflix持续交付实践探寻

内容来源&#xff1a;DevOps案例深度研究 – Netflix的文化与工程实践战队&#xff08;本文只展示部分案例PPT及研究成果&#xff0c;更多细节请关注案例分享活动&#xff0c;及本公众号&#xff09;。本案例内容贡献者&#xff1a;高金梅&#xff0c;李晓莉&#xff0c;潘雄鹰…

深入理解 JVM Class文件格式(六)

经过前几篇文章&#xff0c; 终于将常量池介绍完了&#xff0c; 之所以花这么大的功夫介绍常量池&#xff0c; 是因为对于理解class文件格式&#xff0c;常量池是必须要了解的&#xff0c; 因为class文件中其他地方&#xff0c;大量引用了常量池中的数据项。 对于还不了解常量池…

远程开发初探 - VS Code Remote Development

如果你是学生&#xff0c;你还在你的 windows 电脑上为各种环境配置头疼的时候&#xff0c;你应该了解一下 Remote Development。如果你喜欢 linux 的开发环境和舒适的 shell&#xff0c;但却不舍得抛弃 windows/macos 图形界面给你带来的用户体验和一些软件的兼容(QQ, 微信), …

深入理解 JVM Class文件格式(七)

本专栏列前面的一系列博客&#xff0c; 对Class文件中的一部分数据项进行了介绍。 本文将会继续介绍class文件中未讲解的信息。 先回顾一下上面一篇文章。 在上一篇博客中&#xff0c; 我们介绍了&#xff1a; this_class 对当前类的描述 super_class 对当前类的超类的描述 in…

微信小程序集成腾讯云 IM SDK

1、背景因业务功能需求需要接入IM&#xff08;即时聊天&#xff09;功能&#xff0c;一开始想到的是使用 WebSocket 来实现这个功能&#xff0c;然天意捉弄&#xff08;哈哈&#xff09;服务器版本太低不支持 wx 协议&#xff08;也就不支持 WebSocket了&#xff09;不得不寻找…

深入理解 JVM Class文件格式(八)

在本专栏的第一篇文章 深入理解Java虚拟机到底是什么 中&#xff0c; 我们主要讲解了什么是虚拟机&#xff0c; 这篇博客是对JVM的一个概述。 在随后的几篇文章中&#xff0c;一直在讲解class文件格式。 在今天这篇博客中&#xff0c; 将会继续讲解class文件中的其他信息。 在本…

深入理解 JVM Class文件格式(九)

经过前八篇关于class文件的博客&#xff0c; 关于class文件格式的内容也基本上讲完了。 本文是关于class文件格式的最后一篇。 在这篇博客中&#xff0c; 将会讲解关于方法的几个属性。 理解这篇博客的内容&#xff0c; 对于理解JVM执行引擎起着重要作用。 关于虚拟机执行引擎有…

MongoDB入门及 c# .netcore客户端MongoDB.Driver2.9.1使用

MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。什么场景下使用MongoDBMongoDB虽然是NoSQL(非关系型的数据库)&#xff0c;但是实际使用的时候可以当做关系型数据库来用&#xff0c;mysql等数据库中单表数据量…

《WTM送书活动:向更遥远的星辰大海起航~》

点击上方蓝字关注我们吧是的,没错~这一篇不是大老刘写的 哈哈~啥? 你想知道为啥? 大老刘为了你们不加班,熬夜改BUG,姑娘不乐意了...然后...后面请自行脑补~哎~生活还要继续鸭....那么,接下来由我陪大家唠一段儿~ 单口...各位看官老爷们:注意了!第一件事情呢我们的WTM框…

Java中的对象一定在堆上分配吗?

首先&#xff0c;为解释这个问题&#xff0c;需要的基本知识如下&#xff08;如果对以下概念不太熟悉&#xff0c; 可以先了解下&#xff09;&#xff1a; 1.JVM内存结构&#xff0c;传送门 2.即时编译&#xff08;JIT&#xff09;&#xff0c;传送门 3. 逃逸分析&#xff0c;…

最全的 netcore 3.0 升级实战方案

1、哈喽大家中秋节&#xff08;后&#xff09;好呀&#xff01;感觉已经好久没有写文章了&#xff0c;但是也没有偷懒哟&#xff0c;我的视频教程《系列一、NetCore 视频教程&#xff08;Blog.Core&#xff09;》也已经录制八期了&#xff0c;还在每周末同步更新中&#xff0c;…

微软发布.Net Core 3.0 RC1,最终版本定于9月23日

2019.9.17 微软 宣布推出.NET Core 3.0 Release Candidate 1。就像Preview 9一样&#xff0c;主要专注于为 .NET Core 3.0 发布最终版本 。现在变得非常非常接近。将在9月23日.NET Conf上发布最终版本。.NET Core 3.0是从仅支持Windows传统的 .NET框架向更现代化的开源实现过渡…

JVM内存结构 VS Java内存模型 VS Java对象模型

Java作为一种面向对象的&#xff0c;跨平台语言&#xff0c;其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似&#xff0c;很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模型和Java对象模型&#xff0c;这就是三个截然不同的概念&…