返回

别再纠结链表反转了,一文为你揭秘算法要点与典型题解!

后端

掌握链表反转,踏上算法高手之路

在算法工程的广阔世界里,链表反转是一项必备的技能,是算法高手必备的垫脚石。作为链表操作的基础,链表反转不仅是编程竞赛中的常见考点,更是在实际开发中解决众多链表相关问题的关键。掌握链表反转,不仅能让你在算法竞赛中脱颖而出,还能极大提升你在实际开发中的问题解决能力。

理解链表反转的精髓:颠倒节点顺序

链表反转的精髓在于将链表中节点的顺序逐个颠倒,形成一个新的链表。这个过程看似简单,却蕴含着深刻的算法思想。

形象地比喻,链表反转就像将一串珍珠项链从头到尾一个个取下来,然后从尾到头重新串起来。链表反转的核心算法主要有迭代法和递归法两种:

迭代法:逐步断开节点,重新连接

迭代法就像沿着项链逐个摘取珍珠,并将它们重新串成一条新的项链。具体步骤如下:

  1. 将原链表的第一个节点作为新链表的头节点。
  2. 从原链表的第二个节点开始,依次断开每个节点,并将其插入新链表的头节点前面。
  3. 重复步骤 2,直到所有节点都被反转。

递归法:从最后一个节点递归

递归法就像从项链末端开始拆卸,然后逐个连接到新项链的首端。具体步骤如下:

  1. 将原链表的最后一个节点作为新链表的头节点。
  2. 将原链表的倒数第二个节点作为新链表的第二个节点,并将倒数第三个节点连接到它后面。
  3. 递归地反转剩余的链表,直到所有节点都被反转。

代码实现:C++ 和 Java 实例

为了巩固你的理解,我们提供了 C++ 和 Java 两种语言的链表反转代码实现:

C++ 实现:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

Java 实现:

public class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

LeetCode 206:反转链表

作为 LeetCode 上最经典的链表反转题目之一,206 要求你反转一个给定的链表。为了帮助你理解和解决这一问题,我们提供了 C++ 和 Java 两种语言的实现:

C++ 实现:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        ListNode* next = nullptr;
        while (curr != nullptr) {
            next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

Java 实现:

public class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

牛客网 78:反转链表(含环)

牛客网 78 题与 LeetCode 206 类似,但增加了链表可能包含环的复杂性。为了处理这种情况,你需要在反转链表的同时,判断链表中是否存在环。我们同样提供了 C++ 和 Java 两种语言的实现:

C++ 实现:

class Solution {
public:
    bool hasCycle(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (slow != nullptr && fast != nullptr && fast->next != nullptr) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }

    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr != nullptr) {
            ListNode* next = curr->next;
            if (hasCycle(curr)) {
                return nullptr;
            }
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

Java 实现:

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (slow != null && fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }

    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            if (hasCycle(curr)) {
                return null;
            }
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

常见问题解答

  1. 什么是链表反转?
    反转链表是指将链表中节点的顺序逐个颠倒,形成一个新的链表。

  2. 链表反转有哪些算法?
    常用的链表反转算法有迭代法和递归法。

  3. 如何判断链表中是否存在环?
    可以使用快慢指针法,如果快指针追上了慢指针,则说明链表中存在环。

  4. 环形链表能反转吗?
    不能,因为环形链表中没有起点和终点,无法确定反转的方向。

  5. 链表反转在实际开发中有什么作用?
    链表反转在实际开发中可以用于解决各种链表相关问题,如判断回文链表、删除倒数第 k 个节点、合并两个有序链表等。

结语

掌握链表反转是成为算法高手必备的技能。通过理解其精髓、掌握两种核心算法以及练习典型题目,相信你能熟练运用链表反转,为你在算法竞赛和实际开发中披荆斩棘,打开胜利之门。