算法小练习之分割链表

65 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

1、前言

每天一个算法小练习,本篇使用Java实现。

2、题目描述

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

  • 链表中节点的数目在范围 [0, 200] 内
  • -100 <= Node.val <= 100
  • -200 <= x <= 200

2.1、示例1

image.png

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

2.2、示例2

输入:head = [2,1], x = 2
输出:[1,2]

3、解题思路

这道题刚开始读了好几遍才理解题意,尤其是4为什么在3的前面...其实可以这么理解,从链表的头节点开始遍历,只要遇到比 x 大的值就将其取出来,然后再与剩下的原链表拼接起来。那么我们可以找到第一个大于等于x的节点,然后用头插法的方式将小于x的节点插入这个节点之前,即可保持相对顺序不变。

3.1、双指针

class Solution {
    public ListNode partition(ListNode head, int x) {
        ListNode small = null, current = head, large = null;
        while (current != null) {
            // 交换条件 小于目标值 不是头部 相邻节点不是都小于目标值
            if (current.val < x && large != null && large != small) {
                if (small == null) { 
                    // 如果是头部节点需要被交换
                    large.next = current.next;
                    current.next = head;
                    head = current;
                    small = current;
                    current = large.next;
                } else {
                    if (current.next == null && head == large) { 
                        // 如果只有两个节点
                        if (large.val > x) {
                            // 前一个节点大于目标值则交换
                            large.next = null;
                            current.next = large;
                            head = current;
                        }
                        current = null;
                    } else {
                        large.next = current.next;
                        current.next = small.next;
                        small.next = current;
                        small = small.next;
                        current = large.next;
                    }
                }
            } else {
                //头部或相邻节点都是小于目标值则更新慢指针的值
                if ((large == null || large == small) && current.val < x) {
                    small = current;
                }
                large = current;
                current = current.next;
            }
        }
        return head;
    }
}

执行结果:

image.png

  • 时间复杂度:O(N)O(N),n为链表长度

  • 空间复杂度:O(1)O(1)

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊