1. 程式人生 > 其它 >【LeetCode】連結串列問題:雙指標或回溯

【LeetCode】連結串列問題:雙指標或回溯

技術標籤:# LeetCodeleetCode

雙指標或回溯

  • 對於連結串列中要拿到後幾個元素的問題,一定是雙指標
  • 對於連結串列前幾個元素要使用後面的元素,那麼可以遞歸回溯

19. 刪除連結串列的倒數第 N 個結點

難度中等1199收藏分享切換為英文接收動態反饋

給你一個連結串列,刪除連結串列的倒數第 n 個結點,並且返回連結串列的頭結點。

**進階:**你能嘗試使用一趟掃描實現嗎?

示例 1:

在這裡插入圖片描述

輸入:head = [1,2,3,4,5], n = 2
輸出:[1,2,3,5]

示例 2:

輸入:head = [1], n = 1
輸出:[]

示例 3:

輸入:head = [1,2], n = 1
輸出:[1]

提示:

  • 連結串列中結點的數目為 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

題解

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode firstNode = new ListNode();
        firstNode.next = head;

        ListNode p = firstNode , q = firstNode;
        int step =
0; while(q != null){ if(step >= n + 1){ p = p.next; } step ++; q = q.next; } p.next = p.next.next; return firstNode.next; } }

61. 旋轉連結串列

難度中等412收藏分享切換為英文接收動態反饋

給定一個連結串列,旋轉連結串列,將連結串列每個節點向右移動 k

個位置,其中 k 是非負數。

示例 1:

輸入: 1->2->3->4->5->NULL, k = 2
輸出: 4->5->1->2->3->NULL
解釋:
向右旋轉 1 步: 5->1->2->3->4->NULL
向右旋轉 2 步: 4->5->1->2->3->NULL

示例 2:

輸入: 0->1->2->NULL, k = 4
輸出: 2->0->1->NULL
解釋:
向右旋轉 1 步: 2->0->1->NULL
向右旋轉 2 步: 1->2->0->NULL
向右旋轉 3 步: 0->1->2->NULL
向右旋轉 4 步: 2->0->1->NULL

題解

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        int sum = 0;
        ListNode node = head;
        while(node != null){
            sum ++;
            node = node.next;
        }

        if(sum == 0){
            return null;
        }
        k = k % sum;
        
        ListNode p = head , q = head;
        int step = 0;

        while(q.next != null){
            if(step >= k){
                p = p.next;
            }
            step ++;
            q = q.next;
        }

        q.next = head;
        head = p.next;
        p.next = null;
        return head;
    }


}

143. 重排連結串列

難度中等512收藏分享切換為英文接收動態反饋

給定一個單鏈表 LL0→L1→…→L**n-1→Ln ,
將其重新排列後變為: L0→L**nL1→L**n-1→L2→L**n-2→…

你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。

示例 1:

給定連結串列 1->2->3->4, 重新排列為 1->4->2->3.

示例 2:

給定連結串列 1->2->3->4->5, 重新排列為 1->5->2->4->3.

題解

  • 正規解法:找到中間位置(快慢指標,快的走兩步,慢的走一步)-> 對後半段反轉 -> 歸併

回溯解法

class Solution {
    public void reorderList(ListNode head) {
        int sum = 0;
        ListNode node = head;
        while(node != null){
            node = node.next;
            sum ++;
        }
        
        if(sum != 0){
            func(head , 1 , sum);
        }
    }

    ListNode func(ListNode head , int level , int sum){
        int midSum = (sum % 2 == 0) ? sum / 2 : sum / 2 + 1;
        if(level == midSum){
            if(sum % 2 != 0){
                ListNode res = head.next;
                head.next = null;
                return res;
            }

            ListNode res = head.next.next;
            head.next.next = null;
            return res;
        }

        ListNode next = func(head.next , level + 1 , sum);
        if(next == null){
            return null;
        }
        ListNode res = next.next;

        next.next = head.next;
        head.next = next;

        return res; 
    }
}

234. 迴文連結串列

難度簡單840收藏分享切換為英文接收動態反饋

請判斷一個連結串列是否為迴文連結串列。

示例 1:

輸入: 1->2
輸出: false

示例 2:

輸入: 1->2->2->1
輸出: true

題解

  • 正規解法:雙指標找到中間,分成兩個連結串列,然後比較

回溯

class Solution {
    boolean isTrue = true;
    public boolean isPalindrome(ListNode head) {
        ListNode node = head;
        int sum = 0;
        while(node != null){
            node = node.next;
            sum ++;
        }

        func(head , 1 ,sum);
        return isTrue;
    }

    ListNode func(ListNode head , int level , int sum){
        int midLevel = sum / 2 + 1;
        if(level == midLevel){
            if(sum % 2 == 0){
                return head;
            }
            return head.next;
        }

        ListNode node = func(head.next , level + 1, sum);
        if(node.val != head.val){
            isTrue = false;
        }

        return node.next;
    }
}