鏈表反轉


鏈表

class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
    }
}

反轉鏈表

/**
 * 反轉鏈表:頭節點插入法
 * 
 * 時間復雜度:O(n)。
 * 空間復雜度:O(1)。
 */
class Solution1 {
    public static ListNode reverse(ListNode head) {
        //newHead為頭節點
        ListNode newHead = null;
        //當前節點
        ListNode cur = head;
        while (cur != null) {
            //保存當前節點的下一個節點
            ListNode next = cur.next;
            /**
             * 處理當前節點
             */
            //將處理好的節點添加到當前節點后面
            cur.next = newHead;
            //當前節點變為頭節點
            newHead = cur;
            cur = next;
        }
        return newHead;
    }
}


/**
 * 反轉鏈表:遞歸法
 * 
 * 時間復雜度:O(n)。
 * 空間復雜度:O(n),由於使用遞歸,將會使用隱式棧空間。遞歸深度可能會達到 n 層。
 */
class Solution2 {
    public static ListNode reverse(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        /**
         * 返回最后一個節點,作為head節點(當head.next為最后一行節點,會返回head.next)
         *
         * 反轉head.next之后的節點
         */
        ListNode p = reverse(head.next);
        /**
         * 反轉head節點
         *
         * 將后一個節點的前一個節點反轉。
         *
         * head.next為后一個節點,head為前一個節點。
         * 后一個節點的next指向前一個節點,前一個節點指向null。
         *
         * 以此向前推
         */
        head.next.next = head;
        head.next = null;
        return p;
    }
}

頭插法

給定一個鏈表,旋轉鏈表,將鏈表每個節點向右移動 k 個位置,其中 k 是非負數

/**
 * 給定一個鏈表,旋轉鏈表,將鏈表每個節點向右移動 k 個位置,其中 k 是非負數
 * 
 * 思路:
 *     將鏈表閉合成環,然后在合適的地方斷開(移動k位就從結尾截取k位到頭節點)
 * 
 * 時間復雜度:O(N)。
 * 空間復雜度:O(1)。
 */
class Solution3 {
    public ListNode rotateRight(ListNode head, int k) {
        //k==0則返回
        if (k == 0) {
            return head;
        }

        //非空鏈表
        int len = 0;
        if (head != null) {
            //計算鏈表長度
            len++;
            ListNode cur = head;
            while (cur.next != null) {
                len++;
                cur = cur.next;
            }

            //閉合成環
            cur.next = head;

            //找到何時的位置並斷開
            ListNode pre = head;
            for (int i = 0; i < len - k % len - 1; i++) {
                pre = pre.next;
            }
            head = pre.next;
            pre.next = null;
            return head;
        }

        //空鏈表直接返回
        return head;
    }
}

移位

反轉從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉(1 ≤ m ≤ n ≤ 鏈表長度)

/**
 * 反轉從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉(1 ≤ m ≤ n ≤ 鏈表長度):遞歸法
 * <p>
 * 思路:
 * 創建兩個指針,一個開頭,一個結尾。不斷地交換這兩個指針的值,並將兩個指針向中間移動。
 *
 * 時間復雜度: O(N)。對每個結點最多處理兩次。遞歸過程,回溯。
 * 空間復雜度: 最壞情況下為 O(N)。
 */
class Solution4 {
    ListNode left;
    boolean flag;

    /**
     * 只有rigth需要往回走
     */
    public void recursionAndReverse(ListNode rigth, int m, int n) {
        //n需要走n步才能到達n的位置,每走一步n-1
        if (n == 1) {
            return;
        }
        //m只需要走m步
        if (m > 1) {
            left = left.next;
        }
        rigth = rigth.next;

        recursionAndReverse(rigth, m - 1, n - 1);

        //兩個指針重合說明已經交換完畢,不需要再交換了。
        if (left == rigth || rigth.next == left) {
            flag = true;
        }
        if (!flag) {
            int tmp = left.val;
            left.val = rigth.val;
            rigth.val = tmp;
            left=left.next;
        }
    }

    public ListNode reverseBetween(ListNode head, int m, int n) {
        if (head == null || m == n || n == 1) {
            return head;
        }
        left = head;
        flag = false;
        recursionAndReverse(head, m, n);
        return head;
    }
}

遞歸交換


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM