开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情
206.反转链表
题意:反转一个单链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
链表中节点的数目范围是 [0, 5000] -5000 <= Node.val <= 5000
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
双指针法
其实看到这道题,我最开始想的是定义一个新的链表,但是那样又太麻烦了,而用双指针解法可以直接在原链表上进行更改,就方便得多了。
大体思路就是一个接一个的改变每一个指针的指向,这里就可以用循环,当然我们也可以用递归,这个是我们后面那种方法。
设置两个指针,用来改变指针指向,也就是让cur指向prev,但是cur指向prev后,他的下一节点就变为prev了,就找不到之前的下一节点了,为了解决这个问题,我们还需要设置一个临时指针temp,用于记录cur原始的下一个节点。代码就是下面这样。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev=null;
ListNode cur=head;
ListNode temp=null;
while(cur!=null){
temp=cur.next;
cur.next=prev;
prev=cur;
cur=temp;
}
return prev;
}
}
递归写法
递归这种写法单看代码感觉还是挺难懂的,但是其实他和双指针的逻辑都是一样的,只是换了种写法。
比如ListNode prev=null; ListNode cur=head;
换成了return reverse(null,head);
。
同样的, prev=cur; cur=temp;
换成了return reverse(cur,temp);
而相应的,双指针写写法中,判断cur==null
则退出循环,返回prev,在递归的写法中,则写在reverse方法的第一行,也就是if(cur==null) return prev;
。
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null,head);
}
public ListNode reverse(ListNode prev,ListNode cur){
if(cur==null) return prev;
ListNode temp=cur.next;
cur.next=prev;
return reverse(cur,temp);
}
}