给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0≤n≤1000
要求:空间复杂度 O(1) ,时间复杂度 O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
示例1
输入:
{1,2,3}
复制返回值:
{3,2,1}
复制
示例2
输入:
{}
复制返回值:
{}
复制说明:
空链表则输出空
反转:顾名思义就是将前面的变成后边的,将顺序倒置
那么首先可能会想到的是栈,因为栈的思想就是“先进后出”,是一种天然的反转顺序的类型
1.用栈的思想
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
import java.util.Stack;//引用Stack工具类
public class Solution {
public ListNode ReverseList(ListNode head) {
Stack<ListNode> stack = new Stack<>();
//把链表节点全部放到栈中
while (head != null) {
stack.push(head);
head = head.next;
}
//如果是空栈,那么直接返回null
if (stack.isEmpty())
return null;
ListNode node = stack.pop();
ListNode newHead = node; //新的链表头
ListNode tempNode = null; //暂存当前出栈的node
//栈中的结点全部出栈,然后重新连成一个新的链表
while (!stack.isEmpty()) {
tempNode = stack.pop();
node.next = tempNode;
node = node.next;
}
//最后一个结点就是原来的头结点,不要忘记将它的next等于空
node.next = null;
return newHead;
}
}
除了栈符合我们的题目思想之外,本身的思路上应该也是可以的
2.用双指针
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode newHead = null;
ListNode cur = head;
ListNode next = null;
while (cur != null) {
//先定位到下一个节点的位置
next = cur.next;
//将当前节点的下一个节点指向新链表的表头
cur.next = newHead;
//再将新链表的表头重新定位到当前节点
//此时已经实现的当前结点指向前一个节点的操作
newHead = cur;
//将当前结点指向下一个节点,为下一次循环作准备
cur = next;
}
return newHead;
}
}