一、 基本的翻转链表,给头结点,返回翻转后的头结点
206. Reverse Linked List
A -> B -> C
prev cur next
思路是按顺序来,先记录next
的地址,然后将cur.next
指向prev
,接着将prev
和cur
向前平移,直到cur
为null
时间复杂度是O(n),空间复杂度为O(1)
迭代实现
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode prev = null, cur = head;
while(cur != null){ //不能使cur.next != null,那样会错过最后一个节点的反向
ListNode tmp = cur.next;
cur.next = prev;
prev = cur;
cur = tmp;
}
return prev; //cur为null时赋值结束,返回prev
}
}
递归实现,思路是一样的
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
return helper(null, head);
}
public ListNode helper(ListNode prev, ListNode cur){
ListNode node = cur.next;
cur.next = prev;
if(node != null) return helper(cur, node);
else return cur;
}
}
二、 翻转链表中的一部分
92. Reverse Linked List II
题目描述
Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.
Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
分析比较
这一题较上一题需要注意的是翻转中间的一部分与原链表的一个衔接
比如1->2->3->4->5->NULL
,2 3 4进行翻转,翻转后为 4 3 2
需要将4放在1的后面,2的后面也是5
如果简单的像1那样处理,2的后面会是1,肯定是不对的
所以需要记录1和2的位置,即翻转开始前一个节点和第一个结点,在翻转完后整理赋值。
时间复杂度为O(n),空间复杂度为O(1)
迭代实现
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
if(m == n) return head;
//遍历到要翻转的部分,cur为要翻转的第一个节点
//prev.next应该是翻转后的头结点
ListNode cur = head, prev = null;
for(int i = 1; i < m; ++i){
prev = cur;
cur = cur.next;
}
//cur是翻转后的尾节点,需要记录下来用于最后赋值
ListNode end = cur, nextPtr = cur.next;
for(int i = 1; i <= n - m; ++i){
ListNode node = nextPtr.next;
nextPtr.next = cur;
cur = nextPtr;
nextPtr = node;
}
//尾节点拼接到原串中
end.next = nextPtr;
if(prev != null){
prev.next = cur;
return head;
}else{ // m == 1
return cur;
}
}
}
网友评论