鏈表
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;
}
}
遞歸交換