题目:
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
解题思路:
1. 迭代法:
从链表的头结点开始遍历链表,依次将节点的next指向节点前一个节点。
关键:要弄清楚prev,curr,next三者之前的关系。
重要部分:因为遍历链表时,要将当前节点curr.next指向当前节点的前一个节点prev,这样就没有办法继续遍历,所以要在这之前,将curr.next的地址值复制一份给ListNode tempNext。
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
时间复杂度:O(n)
空间复杂度:O(1)
2. 头插法
思想和迭代法一模一样,迭代法里的prev就是newHead.next,都是null,只不过头插法新多了一个ListNode newHead = new ListNode(-1),让它的next = null, 所以代码里的prev都是以newHead.next出现。
个人觉得迭代法清洗明了,头插法反而搞复杂了。
public ListNode reverseList(ListNode head) {
ListNode newHead = new ListNode(-1);
while (head != null) {
ListNode next = head.next;
head.next = newHead.next;
newHead.next = head;
head = next;
}
return newHead.next;
}
时间复杂度:O(n)
空间复杂度:O(1)
3.递归法
递归执行过程:
- 在next=5=head; head.next=null,即返回head=5,并赋值给newHead前,一直调用递归语句:ListNode newHead = reverseList(next);前面的代码:
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
此前递归栈存储的值为:
head next
4 5
3 4
2 3
1 2
- 当next=5=head; head.next=null,return = head=5,此时,递归结束,栈中的元素开始弹出,开始执行递归语句:ListNode newHead = reverseList(next);后面面的代码:
next.next = head;
head.next = null;
return newHead;
5.next = 4 4.next = null
4.next = 3 3.next = null
3.next = 2 2.next = null
2.next = 1 1.next = null
- 栈中元素清空,返回newHead=5
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
ListNode newHead = reverseList(next);
next.next = head; // 反转
head.next = null;
return newHead;
}
时间复杂度:O(n)
空间复杂度:O(n)
来源:CSDN
作者:多问为什么,坚持跑步
链接:https://blog.csdn.net/baihehaitangyijiu/article/details/104913743