leetcode-排序的循环链表

204 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

题目描述

给定循环单调非递减列表中的一个点,写一个函数向这个列表中插入一个新元素 insertVal ,使这个列表仍然是循环升序的。

给定的可以是这个列表中任意一个顶点的指针,并不一定是这个列表中最小元素的指针。

如果有多个满足条件的插入位置,可以选择任意一个位置插入新的值,插入后整个列表仍然保持有序。

如果列表为空(给定的节点是 null),需要创建一个循环有序列表并返回这个节点。否则。请返回原先给定的节点。

 

示例 1:

示例1.jpg

输入:head = [3,4,1], insertVal = 2
输出:[3,4,1,2]
解释:在上图中,有一个包含三个元素的循环有序列表,你获得值为 3 的节点的指针,我们需要向表中插入元素 2 。新插入的节点应该在 1 和 3 之间,插入之后,整个列表如上图所示,最后返回节点 3 。

示例1解释.jpg

示例 2:
输入:head = [], insertVal = 1
输出:[1]
解释:列表为空(给定的节点是 null),创建一个循环有序列表并返回这个节点。

示例 3:
输入:head = [1], insertVal = 0
输出:[1,0]

提示:

  • 0 <= Number of Nodes <= 5 * 10^4
  • -10^6 <= Node.val <= 10^6
  • -10^6 <= insertVal <= 10^6

思路

题目的理解和解都不难,就是要考虑比较多的情况:

  1. 原始链表为空
  2. 原始链表只有一个节点
  3. 原始链表有多个节点,值都相等
  4. 原始链表有多个节点,至少有2个节点值不同,insertVal在(min,max)范围外
  5. 原始链表有多个节点,至少有2个节点值不同,insertVal在(min,max)范围内 处理好上述的5种情况,就可以顺藤摸瓜写出解法。
  6. 原始链表为空,可以直接返回要插入的新节点,注意要形成环,所以新节点的后继要指向自身
  7. 原始链表只有一个节点,新节点插入在head节点后即可
  8. 原始链表有多个节点,值都相等;解法同情况2,插入在head节点后即可
  9. 原始链表有多个节点,至少有2个节点值不同,insertVal在(min,max)范围外;需要找到最后一个值等于max的节点,插入到这个节点后面
  10. 原始链表有多个节点,至少有2个节点值不同,insertVal在(min,max)范围内;找到第一个满足当前值<=insertVal,后继值>=insertVal的节点,插入在这个节点后面

Java版本代码

class Solution {
    public Node insert(Node head, int insertVal) {
        // 构建需要插入的节点
        Node insertNode = new Node(insertVal);
        // 先将节点的后继指向自身
        insertNode.next = insertNode;
        // 原始列表为空,直接返回insertNode
        if (head == null) {
            return insertNode;
        }
        int min = head.val;
        int max = head.val;
        Node originHead = head;
        while (head.next != originHead) {
            head = head.next;
            min = Integer.min(min, head.val);
            max = Integer.max(max, head.val);
        }
        // 如果max == min,代表原始原始链表中的节点值都相等,或者只有1个节点,这种情况下,直接插入在head后面即可
        if (max == min) {
            insertNode.next = originHead.next;
            originHead.next = insertNode;
            return originHead;   
        }
        // 否则,代表原始链表至少有2个值不相等的节点
        if (insertVal <= min || insertVal >= max) {
            // insertVal在(min, max)范围外时,要找到最后一个等于max值的节点,然后插入在这个节点后面
            while (!(head.val == max && head.next.val == min)) {
                head = head.next;
            }
        } else {
            // insertVal在(min, max)范围内时,找到一个当前值<=insertVal,后继值>=insertVal的
            while (!(head.val <= insertVal && head.next.val >= insertVal)) {
                head = head.next;
            }
        }
        insertNode.next = head.next;
        head.next = insertNode;
        return originHead;
    }
}