刷题日记——反转链表

19 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情

206.反转链表

力扣题目链接(opens new window)

题意:反转一个单链表。

示例 1:

输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]

image.png 示例 2:

输入:head = [1,2] 输出:[2,1]

image.png 示例 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);
    }
}