算法通关村第二关——终于学会反转链表了

291 阅读1分钟

青铜挑战:手写链表反转

方法一:利用额外空间——栈来实现链表反转

数据结构中栈的特点就是先进后出,只要把给定链表的每个节点压栈,然后再一个一个出栈连成新链表就可以了。

image.png

image.png

image.png 代码如下:

public static ListNode reverseListMethod2(ListNode head) {
    if (head == null) {
        return head;
    }
    Stack<ListNode> stack = new Stack<>();
    // 先遍历一遍链表,将各个 head 压栈
    while (head != null) {
        stack.push(head);
        head = head.next;
    }
    // 此时栈中栈顶元素即是原链表的尾节点,将它赋值给res返回链表,作为返回链表的头节点
    ListNode res = stack.pop();
    // 申请一个中间节点,让temp移动,而不是让res链表头节点移动;
    // 如果不申请中间节点,使用res来记录栈中弹出的各节点,那么最终res就会变成栈中最后一个弹出的节点,而不是一条链
    ListNode temp = res;
    while (!stack.isEmpty()) {
        ListNode cur = stack.pop();
        // 让 栈中弹出的节点的指针指向 null,保证 cur 是单个节点,而不是链
        cur.next=null;
        temp.next=cur;
        temp = temp.next;
    }
    return res;
}

注意:一定要让 cur.next=null;即让每个弹出的链表节点指向null; 因为栈中记录的并不是单个节点,也可能是链;

方法二:不使用额外空间变量来反转链表

此时就需要改变原链表中各个节点指针的指向;

image.png

image.png

完整代码如下:

// 假设题目输入链表结构为 1-->2-->3-->4-->5
public static ListNode reverseListNode(ListNode head){
    ListNode res=null; // 作为返回节点
    ListNode next=null; // 记录head原来指针的指向;
  
    while(head != null){
         // 单个节点改变指针指向的过程
        next=head.next;
        head.next=res;
        res=head;
        head=next;
    }
    return res;
}

建议将整个过程在纸上画一遍,这样才能容易的理解各个节点指针变化的过程;

结果如下:

image.png