708. Insert into a Cyclic Sorted List

708. Insert into a Cyclic Sorted List


Given a node from a cyclic linked list which is sorted in ascending order, write a function to insert a value into the list such that it remains a cyclic sorted list. The given node can be a reference to any single node in the list, and may not be necessarily the smallest value in the cyclic list.

If there are multiple suitable places for insertion, you may choose any place to insert the new value. After the insertion, the cyclic list should remain sorted.

If the list is empty (i.e., given node is null), you should create a new single cyclic list and return the reference to that single node. Otherwise, you should return the original given node.

The following example may help you understand the problem better:
在这里插入图片描述
In the figure above, there is a cyclic sorted list of three elements. You are given a reference to the node with value 3, and we need to insert 2 into the list.
在这里插入图片描述
The new node should insert between node 1 and node 3. After the insertion, the list should look like this, and we should still return node 3.

方法1:

思路:

注意是sorted。从head出发,目标是找到最后一个小于等于新数字的节点,称为cur,下一个节点称为next,那么我们就可以把新数字插在中间。要处理几种corner cases:

  1. 所有数字都大于new:要找到最大值作为cur,最小值作为next
  2. 所有数字都小于等于new:要找到最大值作为cur,最小值作为next
  3. 空链:创建一个新的节点返回

通过head,我们可以提前判断一下,如果为空,落入第三种情况。遍历开始之后,几种cases需要处理:1. 出现cur <= new <= next, 这种情况只要出现就可以创建返回。2. 出现cur > next,也就是后半部没有合适的插入点,此时可以标记一个end = cur继续循环。可能在前半部分被第一种case打断,也可能回到head都没有找到合适的点。后一种情况可以直接跳掉之前记录的尾节点插入。

易错点

  1. test case全部相等:理论上此时可以在任意位置插入,但如下方法会在循环一圈后退出,如果end没有被赋值,在下一步insert会抛出nullptr错误。解决办法就是修改end的赋值条件为cur > next为cur >= next。
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;

    Node() {}

    Node(int _val, Node* _next) {
        val = _val;
        next = _next;
    }
};
*/
class Solution {
public:
    Node* insert(Node* head, int insertVal) {
        if (!head) {
            Node* node = new Node(insertVal, nullptr);
            node -> next = node;
            return node;
        } 
        
        Node * end = nullptr, * cur = head, * next = head -> next;
        while (true) {
            if (cur -> val <= insertVal && next -> val >= insertVal) {
                insert(cur, next, insertVal);
                return head;
            }
            if (cur -> val >= next -> val) end = cur;
            cur = next;
            next = next -> next;
            if (cur == head) break;
        }
        insert(end, end -> next, insertVal);
        return head;
    }
    
    void insert(Node* cur, Node* next, int insertVal) {
        Node* node = new Node(insertVal, next);
        cur -> next = node;
    }
};

做一些化简:

  1. 当遇到拐点的时候,可以直接获知new是否小于最小或大于最大,可以直接退出
  2. 循环可以不用画满一周整,如果在最后一步之前都没有被任意一种case(遇到合适点或者遇到拐点)打断,那么最后一个未经检查的间隙一定是需要插入的间隙。因为要不然这个点就是两者之一,要不然就是全部相等的corner case。算是一个trick。
  3. 但这时cur > next时才算极值点,因为不可以radically的打断。
class Solution {
public:
    Node* insert(Node* head, int insertVal) {
        if (!head) {
            Node* node = new Node(insertVal, nullptr);
            node -> next = node;
            return node;
        } 
        
        Node * cur = head, * next = head -> next;
        while (next != head) {
            if (cur -> val <= insertVal && next -> val >= insertVal) break;
			if (cur -> val > next -> val && (insertVal <= next -> val || insertVal >= cur -> val)) break;
            
            cur = next;
            next = next -> next;
        }
        cur -> next = new Node(insertVal, next);
        return head;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值