【LeetCode】連結串列問題:雙指標或回溯
阿新 • • 發佈:2021-02-11
技術標籤:# 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
示例 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收藏分享切換為英文接收動態反饋
給定一個單鏈表 L:L0→L1→…→L**n-1→Ln ,
將其重新排列後變為: L0→L**n→L1→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;
}
}