链表指定区间反转

题目:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:

1 ≤ m ≤ n ≤ 链表长度。

输入:1->2->3->4->5->NULL, m = 2, n = 4

输出:1->4->3->2->5->NULL

头插法

Java实现

python 复制代码
    public static ListNode reverseBetween2(ListNode head, int left, int right) {
        // 设置 dummyNode 是这一类问题的一般做法
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode pre = dummyNode;
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }
        ListNode cur = pre.next;
        ListNode next;
        for (int i = 0; i < right - left; i++) {
            next = cur.next;
            cur.next = next.next;
            next.next = pre.next; //注意此处,为啥不能用cur
            pre.next = next;
        }
        return dummyNode.next;
    }

python实现

python 复制代码
    def reverseBetween2(self, head, left, right):
        # 设置 dummyNode 是这一类问题的一般做法
        dummy_node = ListNode(-1)
        dummy_node.next = head
        pre = dummy_node
        for _ in range(left - 1):
            pre = pre.next

        cur = pre.next
        for _ in range(right - left):
            next = cur.next
            cur.next = next.next
            next.next = pre.next
            pre.next = next
        return dummy_node.next

穿针引线法

Java实现

java 复制代码
    public static ListNode reverseListNode(ListNode head, int left, int right) {
        //特殊情况考虑
        if(head == null || head.next == null || left == right){
            return head;
        }
        //建立虚拟节点
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode temp = dummyNode;
        int count =0;
        //找到left前一个节点
        for(;count < left-1;count++){
            temp = temp.next;
        }

        //反转链表开始的位置
        ListNode leftNode = temp.next;
        //记录反转后链表的头节点
        ListNode rightNode = null;
        ListNode next = null;

        //开始反转链表
        for(;count<right;count++){
            next = leftNode.next;
            leftNode.next = rightNode;
            rightNode = leftNode;
            leftNode = next;
        }

        ListNode curRight = rightNode;
        //遍历到链表的尾部
        while (curRight.next != null){
            curRight = curRight.next;
        }
        //让反转区间和区间后面的位置相连接
        curRight.next = leftNode;
        //让区间前面的和反转区间相连接
        temp.next = rightNode;
        return dummyNode.next;
    }

python实现

python 复制代码
    def reverseBetween(self, head, left, right):
        def reverse_linked_list(head):
            # 也可以使用递归反转一个链表
            pre = None
            cur = head
            while cur:
                next = cur.next
                cur.next = pre
                pre = cur
                cur = next

        # 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
        dummy_node = ListNode(-1)
        dummy_node.next = head
        pre = dummy_node
        # 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
        # 建议写在 for 循环里,语义清晰
        for _ in range(left - 1):
            pre = pre.next

        # 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
        right_node = pre
        for _ in range(right - left + 1):
            right_node = right_node.next
        # 第 3 步:切断出一个子链表(截取链表)
        left_node = pre.next
        curr = right_node.next

        # 注意:切断链接
        pre.next = None
        right_node.next = None

        # 第 4 步:反转链表的子区间
        reverse_linked_list(left_node)
        # 第 5 步:接回到原来的链表中
        pre.next = right_node
        left_node.next = curr
        return dummy_node.next
相关推荐
梓䈑2 小时前
【算法题攻略】BFS 解决FloodFill 算法、最短路问题、多源BFS 和 拓扑排序
c++·算法·宽度优先
Adios7945 小时前
设置交集大小至少为2
数据结构·算法·leetcode
shawxlee8 小时前
vue3在public下封装config.js自定义配置动态数据,可在打包后直接修改,方便后端部署及后续维护
前端·javascript·经验分享·vue·团队开发·js·项目优化
kyriewen9 小时前
我给前端项目的接口请求套了6层保护——才发现以前一直在裸奔
前端·javascript·面试
郝亚军10 小时前
如何安装webstorm、Node.js和vue CLI
前端·javascript·vue.js
来一碗刘肉面11 小时前
栈的应用(表达式求值)
数据结构·算法
an3174211 小时前
6MB 组织树大文件性能优化全流程
前端·javascript·vue.js
xiaowang1234shs12 小时前
怪兽轻断食技术深度测评:从断食计时引擎到AI识别算法的工程实践解析
数据库·人工智能·算法·macos·机器学习·p2p·visual studio
小果因子实验室12 小时前
量化研究--策略迁移算法1研究
算法