翻转环形链表的思路

文章目录

题目介绍

在这里插入图片描述

翻转环形链表

题解

  1. 检测链表是否有环并找到环的入口:力扣原题
  2. 将环断开:在找到环的入口后,通过设置指针记录环的信息,然后将环断开,使其成为一个普通的单链表。
  3. 反转单链表
  4. 重新连接环:在完成链表反转后,根据之前记录的环的入口信息,重新将链表连接成环。

代码如下:

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

public class CircularLinkedList {

    // 检测环形链表并返回环的入口节点
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        
        ListNode slow = head;
        ListNode fast = head;
        
        // 使用快慢指针检测环
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            
            if (slow == fast) {
                // 找到环后,重置慢指针到头部
                slow = head;
                while (slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow; // 返回环的入口节点
            }
        }
        
        return null; // 无环
    }

    // 普通链表翻转
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        
        return prev;
    }

    // 带环链表翻转
    public ListNode reverseListWithCycle(ListNode head) {
        ListNode cycleEntry = detectCycle(head);
        
        // 如果不是环形链表,直接翻转
        if (cycleEntry == null) {
            return reverseList(head);
        }
        
        // 找到环入口的前一个节点
        ListNode p = head;
        while (p.next != cycleEntry) {
            p = p.next;
        }
        
        // 断开环
        p.next = null;
        
        // 翻转链表
        ListNode newHead = reverseList(head);
        
        // 重新连接环
        ListNode tail = newHead;
        while (tail.next != null) {
            tail = tail.next;
        }
        tail.next = cycleEntry;
        
        return newHead;
    }

    // 测试方法
    public static void main(String[] args) {
        // 创建测试链表 1->2->3->4->5->2 (形成环)
        ListNode head = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        
        head.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node2; // 形成环
        
        CircularLinkedList solution = new CircularLinkedList();
        
        // 检测环
        ListNode cycleNode = solution.detectCycle(head);
        System.out.println("环入口节点值: " + (cycleNode != null ? cycleNode.val : "无环"));
        
        // 翻转带环链表
        ListNode reversedHead = solution.reverseListWithCycle(head);
        
        // 打印翻转后的链表(注意:由于有环,不能直接遍历打印,会无限循环)
        // 这里只打印前几个节点作为演示
        System.out.print("翻转后的链表前几个节点: ");
        ListNode current = reversedHead;
        for (int i = 0; i < 6 && current != null; i++) {
            System.out.print(current.val + " ");
            current = current.next;
        }
    }
}
### 单链表反转的实现 #### 思路分析 单链表反转的核心在于调整链表中每个节点的 `next` 指针方向,使得原本指向下一个节点的方向变为指向上一个节点。这一操作可以通过迭代法或递归法来完成。 #### 迭代法实现 迭代方法通过遍历整个链表并逐步修改节点之间的连接关系来实现反转。以下是具体代码示例: ```java class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null; // 初始化前驱节点为空 ListNode curr = head; // 当前节点初始化为头节点 while (curr != null) { // 遍历直到当前节点为空 ListNode nextTemp = curr.next; // 保存当前节点的下一节点 curr.next = prev; // 修改当前节点的 next 指向其前驱节点 prev = curr; // 更新前驱节点为当前节点 curr = nextTemp; // 移动到下一节点继续处理 } return prev; // 返回新的头节点(原链表的最后一个节点) } } ``` 上述代码实现了单链表的反转功能[^1]。其中,变量 `prev` 始终表示已经反转部分的新链表头部,而 `curr` 表示正在处理的当前节点。 #### 递归法实现 递归方法利用函数调用栈逐层深入至链表末端后再回溯构建新链表。下面是基于递归方式的代码示例: ```java public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode newHead = reverseList(head.next); head.next.next = head; // 将下一层返回的结果中的尾部指向当前节点 head.next = null; // 断开当前节点与后续节点的关系 return newHead; // 新链表的头节点始终不变 } ``` 此递归版本同样可以完成单链表的反转任务[^2]。需要注意的是,在每次递归过程中都需确保断开原有链接以防止形成环形结构。 #### 边界条件考虑 对于输入为空或者仅含单一节点的情况,应直接返回该节点作为结果无需任何额外操作[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值