反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
思路
1.栈
第一时间想到栈。把节点依次压栈,再依次出栈即可。非常的简单
public ListNode reverseList(ListNode head) {
if(head == null){
return null;
}
if(head.next == null){
return head;
}
Stack<ListNode> stack = new Stack<>();
ListNode node = head;
while (node != null){ //依次压栈
stack.push(node);
node = node.next;
}
ListNode result = stack.pop();
ListNode assist = result;
while (!stack.empty()){
assist.next = stack.pop(); //依次出栈
assist = assist.next;
}
assist.next = null; //关键,最后一个节点还是指向倒数第二个节点,将他的next置空,否则出现环
return result;
}
2.迭代
从头到尾,依次改变next指向方向,由于改变了方向,失去原本next元素的引用,需要每次将next元素保存起来。
public ListNode reverseList(ListNode head) {
ListNode node = head; //遍历的元素
ListNode prev = null; //每次指向前一个元素
while(node != null){
ListNode next = node.next; //要让node节点指向前一个节点,要保存一下后面的节点
node.next = prev; //改变链表的指向
prev = node; //移动前一个元素
node = next; //移动遍历的元素
}
return prev;
}
复杂度分析
- 时间复杂度:O(n),假设 n 是列表的长度,时间复杂度是 O(n)。
- 空间复杂度:O(1)。
3.递归(比较复杂)
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode p = reverseList(head.next);
head.next.next = head;
head.next = null;
return p;
}