LeetCode 86. 分隔链表

作者: TheKey_ | 来源:发表于2019-07-09 11:49 被阅读0次

    86. 分隔链表

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

    • 你应当保留两个分区中每个节点的初始相对位置。
    示例1:
    输入: head = 1->4->3->2->5->2, x = 3
    输出: 1->2->2->4->3->5
    

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/partition-list/
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


    • 1.迭代法

    思路:(使用指针)

    1. 将当前节点值小于 x 的放入一个链表中, 大于 x 的放入一个链表中
    2. 将大于 x 的链表拼接到小于 x 的链表之后即可
    image.png
    public static class ListNode {
    
            private int val;
            private ListNode next;
    
            public ListNode(int val) {
                this.val = val;
            }
    
            //用于测试用例
            public ListNode(int[] arr) {
                if (arr == null || arr.length == 0) throw new NullPointerException("array is Empty");
                this.val = arr[0];
                ListNode cur = this;
                for (int i = 1; i < arr.length; i++) {
                    cur.next = new ListNode(arr[i]);
                    cur = cur.next;
                }
            }
    
            @Override
            public String toString() {
                StringBuilder res = new StringBuilder();
                ListNode cur = this;
                while (cur != null) {
                    res.append(cur.val + "->");
                    cur = cur.next;
                }
                res.append("NULL");
                return res.toString();
            }
    
        }
    
       public static ListNode partition(ListNode head, int x) {
            if (head == null) return head;
            ListNode dummyHead = new ListNode(0);
            dummyHead.next = head;
            ListNode cur = head;
            ListNode prev = dummyHead;
            ListNode node = new ListNode(0);
            ListNode p = node;
            while (cur != null) {
                if (cur.val >= x) {
                    prev.next = cur.next;
                    p.next = new ListNode(cur.val);
                    p = p.next;
                } else {
                    prev = prev.next;
                }
                cur = cur.next;
            }
            prev.next = node.next;
            return dummyHead.next;
        }
    

    复杂度分析:

    • 时间复杂度:O(n), n 为链表的长度,我们需要遍历整个链表

    • 空间复杂度:O(x), x 为大于 x 的节点数量,由于我们需要将大于 x 的单独创建节点,所以时间复杂度为 O(x)

    • 2. 改进方法1

    思路:
    同上,只是不在多余创建节点

     public static ListNode partition(ListNode head, int x) {
            if (head == null) return head;
            ListNode dummyHead = new ListNode(0);
            dummyHead.next = head;
            ListNode cur = head;
            ListNode prev = dummyHead;
            ListNode node = new ListNode(0);
            ListNode p = node;
            while (cur != null) {
                if (cur.val >= x) {
                    prev.next = cur.next;
                    p.next = cur;
                    p = p.next;
                } else {
                    prev = prev.next;
                }
                cur = cur.next;
            }
            p.next = null;
            prev.next = node.next;
            return dummyHead.next;
        }
    

    复杂度分析:

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

    • 空间复杂度:O(1), 不需要单独在创建新的节点,所以只需常数级别的空间复杂度

    • 3. 队列法

    思路:利用队列的先进先出(FIFO)特性

    1. 将原链表中节点大于 x 的压入队列 queue1, 大于的压入 queue2
    2. 创建一个新的链表,依次出队然后拼接到新链表即可
     public static ListNode partition(ListNode head, int x) {
            if (head == null) return head;
            ListNode dummyHead = new ListNode(0);
            dummyHead.next = head;
            ListNode cur = head;
            ListNode prev = dummyHead;
            ListNode node = new ListNode(0);
            ListNode p = node;
            while (cur != null) {
                if (cur.val >= x) {
                    prev.next = cur.next;
                    p.next = cur;
                    p = p.next;
                } else {
                    prev = prev.next;
                }
                cur = cur.next;
            }
            p.next = null;
            prev.next = node.next;
            return dummyHead.next;
        }
    

    复杂度分析:

    • 时间复杂度:O(n), n 为链表长度
    • 空间复杂度:O(n + n),时间复杂度为两个队列的空间 + 新链表的长度
    • 测试用例

    public static void main(String[] args) {
             int[] arr = new int[] {1, 4, 3, 2, 5, 2};
             ListNode listNode = new ListNode(arr);
             System.out.println(listNode);
             System.out.println("分割链表:" + partition(listNode, 3));
        }
    
    • 结果

    1->4->3->2->5->2->NULL
    分割链表:1->2->2->4->3->5->NULL
    

    • 源码

    • 我会每天更新新的算法,并尽可能尝试不同解法,如果发现问题请指正
    • Github

    相关文章

      网友评论

        本文标题:LeetCode 86. 分隔链表

        本文链接:https://www.haomeiwen.com/subject/bnztkctx.html