/** * 思路一:因为题目没有要求原地翻转,最简单就我们可以创建一个新链表 * 用一个虚拟头节点,去遍历原来的链表,遇到一个节点就头插一次 * 这样得到的新链表就是跟原来反过来了。 */
示例代码:
public ListNode reverseList(ListNode head) {
//创建一个虚拟头节点,方便头插
ListNode dummyHead = new ListNode();
while(head != null){
ListNode node = new ListNode(head.val);//每次的新节点
node.next = dummyHead.next;
dummyHead.next = node;
head = head.next;
}
return dummyHead.next;
}
//注释:但是如果题目要求空间复杂度为O(1)--> 这个解法就废了
/迭代法:
/** * 思路2:原地移动链表。 所谓的链表反转就是相当于 原来的 1 -》 2 变成了 2 -》 1 * 把每个节点的 原来的 所指向的方法反一下就可以了。 * 用 两个指针 prve 和 cur 来实现相反,再加上一个指针 next记录下 * 一个节点的地址,保持三指针的移动。 * 注释:当 cur走到null的时候, 你会发现 此时的prve正好在 链表末尾上, * 到时候直接返回 prve就可以了 */
示例代码:
public ListNode reverseList(ListNode head) {
ListNode prve = null;//因为要让第一个节点指向null
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;//记录下一个节点的地址,不然等会反转就找不到了
cur.next = prve;
prve = cur;//移动一位
cur = next;//移位移位
}
return prve;
}
递归法:
/** * 思路三:运用递归法来解决。 可以这么拆分:我们每次都知道头节点,所以我们也只 * 处理头节点的情况, 把 head.next交给子方法去解决。后用 prve 接受一下返回地址, * 因为它就是接下来新链表的头节点了 * 然后我们手动把头节点移动到链表末尾 * 注释:记得先保存链表的第二个节点地址,因为等会交给子方法翻转后它就是末尾了。 */
public ListNode reverseList(ListNode head) {
//什么情况下可以不用拆分,或者可以直接知道答案?
if(head == null || head.next == null){
return head;
}
//到这说明至少有两个节点了
ListNode node = head.next;//保存地址,方便等会头节点插它后面
ListNode prve = reverseList(head.next);//这就是新链表的头节点,保存下来
node.next = head;
head.next = null;//不置空 会 回环
return prve;
}