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

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

示例:

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

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

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

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

对应的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)。下面分别给出不同语言的代码实现。

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

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

Leetcode 86. 分隔链表相关推荐

  1. LeetCode 86. 分隔链表 中等难度

    题目 给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前.你应当保留两个分区中每个节点的初始相对位置. 示例: 输入: head = 1->4- ...

  2. 23. Leetcode 86. 分隔链表 (链表-基础操作类-分隔链表)

    给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前.你应当 保留 两个分区中每个节点的初始相对位置.示例 1:输入: ...

  3. leetcode 86. 分隔链表(链表)

    给你一个链表和一个特定值 x ,请你对链表进行分隔,使得所有小于 x 的节点都出现在大于或等于 x 的节点之前. 你应当保留两个分区中每个节点的初始相对位置. 示例: 输入:head = 1-> ...

  4. 【LeetCode】86. 分隔链表

    86. 分隔链表 题解 这题不难,事先准备两个链表,遍历题目给的链表,将小于x和大于等于x的两类数据分别放到准备好的链表中,然后两个链表拼接即可: 注意点: 链表在创建增加的时候,游走的那个指针在当前 ...

  5. 86. 分隔链表 golang

    86. 分隔链表 只把小的放在一边,大于的不用放到右边(这个题的题目比较晦涩,很多人说看不懂题,我也没看懂,解法也没什么特殊,半天没读懂题,看了别人的解法) 给定一个链表和一个特定值 x,对链表进行分 ...

  6. 小黑leetcode之旅:86. 分隔链表

    小黑做法:硬做 # Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None ...

  7. LeetCode 86分割链表87扰乱字符串

    微信搜一搜:bigsai 专注于Java.数据结构与算法,一起进大厂不迷路! 算法文章题解全部收录在github仓库bigsai-algorithm,求star! 关注回复进群即可加入力扣打卡群,欢迎 ...

  8. LeetCode 725. 分隔链表

    1. 题目 给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分. 每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null. ...

  9. LeetCode 725 分隔链表

    题目 给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分. 每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null. 这k个 ...

最新文章

  1. 【错误记录】Ubuntu 安装软件报错 ( Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource tempora )
  2. 十六款值得关注的NoSQL与NewSQL数据库--转载
  3. Kernel Method的理解
  4. SQL学习(三)之子句和函数
  5. 【JS】执行上下文(ExcecutionContext)
  6. java在文本区输出方法_Java文件的几种读取、输出方式
  7. python求最小公倍数_python求最大公约数和最小公倍数的简单方法
  8. 中国电信学院c语言题库,电脑题库试题精编版.doc
  9. OpenStack Glance简介
  10. 无法支持python程序的编辑运行和调试_python程序的调试方法
  11. 一小时学习(一)遍历算法
  12. 代码大全旁边的一本书--感受《UNIX编程艺术》
  13. 幸福之路---罗素,2017-12-6 周三
  14. centos7安装RabbitMQ详细过程
  15. 【Redis数据结构 List 类型】List 类型生产中的应用 消息队列、排行榜、老干妈的朋友圈、监控程序的实现
  16. ask调制流程图_bpsk调制原理
  17. CDN是什么?为何要用CDN加速网站?
  18. 中序和后序构建二叉树
  19. 理解RNN、LSTM、GRU和Gradient Vanishing
  20. 【ECCV2018 UPDT】Unveiling the Power of Deep Tracking[特征融合]

热门文章

  1. WCF发布到IIS7问题的解决方案
  2. 《划时代-51单片机C语言全新教程》-第四章 工程创建与深入 概览
  3. leetcode 128最长连续序列
  4. K8S集群Master高可用实践
  5. flex容器属性(一)
  6. linux centos7 root密码重置
  7. 海量数据处理方法的分析
  8. 如何优雅地处理 EF Core 异常
  9. 将k8s制作成3D射击游戏,好玩到停不下来,附源码
  10. 聊一聊Yarp结合Nacos完成服务发现