每日一題——分隔鏈表

菜雞每日一題系列打卡86

每天一道算法題目 

小夥伴們一起留言打卡

堅持就是勝利,我們一起努力!

題目描述(引自LeetCode)

給定一個鏈表和一個特定值x,對鏈表進行分隔,使得所有小於x的結點都在大於或等於x的結點之前。

你應當保留兩個分區中每個結點的初始相對位置。

示例:
輸入: head = 1->4->3->2->5->2, x = 3
輸出: 1->2->2->4->3->5

題目分析

這是一道鏈表的題目,菜雞將採用迭代的方式進行解決,通過一定的指針操作,實現原地分隔將鏈表分成兩條鏈表(如果可能的話),其中一條鏈表的值都小於x,另一條鏈表的值都大於等於x

爲了操作方便,可以引入啞結點,如果不想引入啞結點,也可以不引入。菜雞將給出兩種解答方式,供大家參考。

代碼實現

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
// 引入啞結點的解答方式
class Solution {


    public ListNode partition(ListNode head, int x) {
        // 特殊情況處理
        if (head == null || head.next == null) return head;
        // 設置啞結點
        ListNode small = new ListNode(-1), sTmp = small;
        ListNode big = new ListNode(-1), bTmp = big;
        // 遍歷鏈表,並將鏈表以x爲界拆成兩條鏈表
        while (head != null) {
            if (head.val < x) {
                sTmp.next = head;
                sTmp = sTmp.next;
            } else {
                bTmp.next = head;
                bTmp = bTmp.next;
            }
            head = head.next;
        }
        // 處理尾結點
        bTmp.next = null;
        // 合併兩條鏈表
        sTmp.next = big.next;
        // 返回結果
        return small.next;
    }


}
// 不引入啞結點的解答方式
class Solution {


    public ListNode partition(ListNode head, int x) {
        // 特殊情況處理
        if (head == null || head.next == null) return head;
        // 申請兩個變量作爲拆分鏈表的表頭
        ListNode small = null, big = null;
        // 申請兩個變量用於拆分鏈表的操作
        ListNode sTmp = small, bTmp = big;
        while (head != null) {
            // 當前值小於x,並且表頭small爲空
            if (head.val < x && small == null) {
                small = head;
                sTmp = head;
            } 
            // 當前值大於等於x,並且表頭big爲空
            else if (head.val >= x && big == null) {
                big = head;
                bTmp = head;
            } 
            // 當前值小於x
            else if (head.val < x) {
                sTmp.next = head;
                sTmp = sTmp.next;
            } 
            // 當前值大於等於x
            else {
                bTmp.next = head;
                bTmp = bTmp.next;
            }
            // 迭代
            head = head.next;
        }
        // 如果大於等於x的鏈表不爲空,則設置尾結點指向null
        if (bTmp != null) bTmp.next = null;
        // 如果小於x的鏈表不爲空,則設置尾結點指向大於等於x鏈表的頭結點
        if (sTmp != null) sTmp.next = big;
        // 返回結果
        return small != null ? small : big;
    }


}

代碼分析

對代碼進行分析,無論是引入啞結點還是不引入啞結點,程序都對鏈表進行了一次遍歷,時間複雜度爲O(n);而就空間而言,兩種解決方式都只使用了常數級別的額外空間,空間複雜度爲O(1)。

執行結果

引入啞結點的執行結果

不引入啞結點的執行結果

基於leetcode的測試集,可以看出兩種方式的執行結果並無明顯區別。

學習 | 工作 | 分享

????長按關注“有理想的菜雞

只有你想不到,沒有你學不到

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章