高频算法题之链表反转

文章目录

  • 前言
  • 递归解题法
  • 栈特性解题法
  • 双指针解题法
  • 总结


前言

复盘一下最近遇到的面试算法题,本篇主要介绍的是链表反转的3种解法和思路,其实有在LeetCode或牛客网上刷题的也知道 链表反转的面试题频率非常高,是必会的一道算法题。

先定义一个单向链表,代码如下:

    /**
     * 链表节点
     */
    private static class Node {
        int data;
        Node next;

        Node(int data) {
            this.data = data;
        }
    }

递归解题法

先上代码,代码如下:

    /**
     * 递归解题法(链表反转)
     * @param head
     * @return
     */
    public static Node recursion(Node head) {
        //在原链表上找到最后一个节点,然后就可以开始往前递归反转
        if (head == null || head.next == null){
            return head;
        }
        //下一个节点
        Node temp = head.next;
        //递归 反转
        Node newHead = recursion(head.next);
        temp.next = head;
        head.next = null;
        return newHead;
    }

递归法是从最后一个Node开始,在弹栈的过程(递归其实就是栈)中将指针顺序置换的,具体过程如下图所示:
在这里插入图片描述
实现代码非常简练,如果没有理解的可以去自己debug模式调试一下,该方式的实际的时间复杂度是 O(n2) ,空间复杂度是O(1),效率较低。

面试官:这是一种解法,请问如何才能更高效呢?

栈特性解题法

递归方式的反转说白也就是栈的思想,现在直接用栈来实现一个高效的链表反转,代码如下:

    /**
     * 栈特性解法 (链表反转)
     * @param node
     * @return
     */
    public static Stack<Integer> reverserLinkedList(Node node) {
        //栈
        Stack<Integer> nodeStack = new Stack<>();
        //存入栈中,模拟递归开始的栈状态
        while (node != null) {
            nodeStack.push(node.data);
            node = node.next;
        }
        return nodeStack;
    }

代码非常简单,直接利用栈先进后出的特性就ok了,具体过程如下:
在这里插入图片描述
总结一下该解法的时间复杂度为 O(n),空间复杂度为O(n),这也是典型用空间来换时间的思路。

面试官:这种解法,时间上已经是最优的,请问如何在空间上优化呢?

双指针解题法

但凡链表相关的面试题,大多数都可以用指针法来解题,指针法就是在链表遍历的过程中将指针顺序置换具体代码如下:

    /**
     * 双指针解法 (链表反转)
     * @param node
     * @return
     */
    public static Node reverse(Node node) {
        //先前结点
        Node pre = null;
        //临时变量 下一个节点
        Node next = null;
        //遍历原链表
        while (node != null) {
            //临时记录原链表下一个节点
            next = node.next;
            //链表的下一个指向为 pre
            node.next = pre;
            //记录当前节点信息
            pre = node;
            //将原链表变为 next 下次遍历从第下个节点开始
            node = next;
        }
        return pre;
    }

具体解题思路过程如下:
在这里插入图片描述
总结一下该解法的时间复杂度为 O(n),空间复杂度为O(1),指针不算占有空间。

总结

理解算法面试题的思路才是正确的刷题方式,常常有小伙伴们组队刷题,但是总会有人抱怨刷题过几天后就忘记了,那是因为你是为了刷题而刷题(仅仅只是当做面试的八股文)根本没有思考,要多思考才能正真掌握它,思考后甚至可以做到举一反三且可以用到实际项目中,这个才是我们刷题的根本目的。

你可能感兴趣的:(算法,面试,链表,算法,面试)