算法通关村第二关——链表白银挑战

1. 链表指定区间反转

LeetCode92 :给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。

输入:head = [1,2,3,4,5], left = 2, right = 4

输出:[1,4,3,2,5]

算法通关村第二关——链表白银挑战_第1张图片

1.1 头插法

需要找到 前一个 反转的前一个节点 leftNodecur = leftNode.next 就是需要反转的第一个节点,然后 next 变量指向 cur.next,核心就是每次都把 next 节点 换到 leftNode.next,详细看下图

算法通关村第二关——链表白银挑战_第2张图片

代码:

 public static ListNode  reverseList1(ListNode head,int left,int right) {
        ListNode ans = new ListNode(-1);
        ans.next = head;
        ListNode leftNode = ans;

        // 找到 left 对应的节点,pre就是 left 对应的前一个节点
        for (int i = 0; i < left - 1; i++) {
            leftNode = leftNode.next;
        }

        // 从 pre 节点的下一个节点开始
        ListNode cur = leftNode.next;

        for (int i = 0; i < right-left; i++) {
            ListNode next = cur.next;
            cur.next = next.next;
            next.next = leftNode.next;
            leftNode.next = next;
        }

        return ans.next;
    }

1.2 穿针引线法

思路:先把前面不需要反转的节点定义一个 变量 pre(反转值的前一个节点) 保存起来,然后 定义 leftNode 保存 pre.next(需要反转的第一个节点),然后找到最后一个需要反转的节点 rightNode,定义 curr 保存 rightNode 后面的节点(后面不需要反转的节点),然后再将 leftNode 即后面的链表调用函数反转返回即可,注意:要把 rightNode.next = null,不然会把后面不需要的值也进行反转。

 代码:

public static ListNode reverseList2(ListNode head,int left,int right) {
        ListNode ans = new ListNode(-1);
        ans.next = head;


        // 找到 left 位置的前一个节点
        ListNode pre = ans;
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }
        // 从 left 开始分割链表
        ListNode leftNode = pre.next;

        // 找到 right 位置的节点
        ListNode rightNode = leftNode;
        for (int i = 0; i < right - left; i++) {
            rightNode = rightNode.next;
        }

        // 保存 后面不需要反转的节点
        ListNode succ = rightNode.next;

        // 使 rightNode 后面后空
        rightNode.next = null;
        // 使前面不需要反转的也为空
        pre.next = null;

        // 开始反转需要反转的区间
        leftNode = reverse1(leftNode);

        // 拼接三段链表
        pre.next = leftNode;
        leftNode.next = succ;

        return ans.next;
    }

2. 两两交换链表中的节点

LeetCode24.给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

算法通关村第二关——链表白银挑战_第3张图片

首先需要的是一个 cur 节点来保存需要交换节点的 前一个节点,每次循环后使 cur 后面的两个节点交换,然后 cur 在进行连接

算法通关村第二关——链表白银挑战_第4张图片

 代码:

public static ListNode swapperTwo(ListNode head) {
        ListNode ans = new ListNode(-1);
        ans.next = head;

        ListNode cur = ans;

        // 记录cur 后面两个节点
        ListNode next1 = null;
        ListNode next2 = null;

        // 保证循环过后 cur 后面必须有两个节点,否则不满足交换条件
        while (cur.next != null && cur.next.next != null) {
            // 两个需要交换的节点
            next1 = cur.next;
            next2 = cur.next.next;

            next1.next = next2.next;
            next2.next = next1;

            // 虚拟节点拼接反转好的节点
            cur.next = next2;

            // 节点指向下一个需要反转的前一个节点
            cur = next1;
        }

        return ans.next;
    }

你可能感兴趣的:(数据结构与算法,算法,链表,数据结构)