전체 연결 목록 반전 (단순)
매우 간단하고 고전적인 주제입니다. 즉, 1-> 2-> 3-> 4-> 5 에서 5-> 4-> 3-> 2-> 1 로 반전 합니다.
두 가지 사고 방식, 반복 및 재귀가 있습니다. 먼저 그림을 본 다음 코드를보십시오.
1) 반복-클래식 더블 / 3 포인터
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
}
2) 재귀-하위 문제가 해결되었다고 가정
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
전체 연결 목록 반전 (고급)
여기에 또 다른 사고 방식, 즉 지속적으로 "전면을 참조"하는 방법이 있습니다.
1) 어느 노드가 순회되고 어느 노드가 첫 번째 노드로 전진합니다.
2)이 프로세스에는 더미 가상 노드가 필요합니다.
3) 이동하는 이중 포인터는 cur 및 nxt입니다 (cur 중 다음 포인터는 매번 nxt입니다. nxt는 계속 진행하기 때문에 cur은 자동으로 뒤로 이동합니다.)
dummy -> 1 -> 2 -> 3 -> 4 -> 5 提前2
dummy -> 2 -> 1 -> 3 -> 4 -> 5 提前3
dummy -> 3 -> 2 -> 1 -> 4 -> 5 提前4
dummy -> 4 -> 3 -> 2 -> 1 -> 5 提前5
dummy -> 5 -> 4 -> 3 -> 2 -> 1 大功告成!
class Solution {
public ListNode reverseList3(ListNode head) {
if (head == null) {
return null;
}
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
ListNode nxt = null;
while (cur.next != null) {
nxt = cur.next;
cur.next = nxt.next;
nxt.next = pre.next;
pre.next = nxt;
}
return dummy.next;
}
}
연결 목록의 일부 반전 (난이도)
반복과 재귀를 배우는 것만으로도 충분하지만 왜 세 번째 "초기"방법을 배워야합니까? 이 질문에 대비하는 것입니다.
반복 / 재귀를 사용하는 경우 알고리즘과 구현 및 경계 처리가 매우 까다 롭습니다.
1) 왼쪽과 오른쪽의 위치와 센티넬의 위치를 찾기 위해 한 번 횡단하십시오.
2) 연결 목록을 가로 채고, 반복 / 재귀를 사용하여 반전하고, 헤드 / 테일 포인터도 사용합니다.
3) 다시 스플 라이스;
세 번째 방법을 사용하면 한 번만 순회됩니다.
1) for (left)는 pre의 위치를 찾아 수정합니다.
2) (오른쪽-왼쪽) 일부 노드에서 작업을 계속 진행하여 되돌릴 수 있습니다.
3) 끝;
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode pre = dummy;
ListNode cur = null;
ListNode nxt = null;
for (int i = 0; i < left - 1; i++) {
pre = pre.next;
}
cur = pre.next;
for (int i = 0; i < right - left; i++) {
// 这段取“nxt然后提前”的代码,像是在链表上穿针引线 >_<
nxt = cur.next;
cur.next = nxt.next;
nxt.next = pre.next;
pre.next = nxt;
}
return dummy.next;
}
}
끝 끝 E N D