题目描述:
给定循环单调非递减列表中的一个点,写一个函数向这个列表中插入一个新元素 insertVal
,使这个列表仍然是循环升序的。
给定的可以是这个列表中任意一个顶点的指针,并不一定是这个列表中最小元素的指针。
如果有多个满足条件的插入位置,可以选择任意一个位置插入新的值,插入后整个列表仍然保持有序。
如果列表为空(给定的节点是 null
),需要创建一个循环有序列表并返回这个节点。否则。请返回原先给定的节点。
示例:
代码:
class Solution {
public:
Node* insert(Node* head, int insertVal) {
Node* newNode = new Node(insertVal);
if (!head) {
newNode->next = newNode;
return newNode;
}
Node* tmp = head;
int maxV = tmp->val, minV = tmp->val;
while (tmp->next != head) {
tmp = tmp->next;
maxV = max(tmp->val, maxV);
minV = min(tmp->val, minV);
}
if (maxV == minV){
newNode->next = tmp->next;
tmp->next = newNode;
return head;
} else {
if (insertVal <= minV || insertVal >= maxV) {
while (tmp) {
if (tmp->val == maxV && tmp->next->val == minV) {
newNode->next = tmp->next;
tmp->next = newNode;
return head;
}
tmp = tmp->next;
}
} else {
while (tmp) {
if (tmp->val <= insertVal && insertVal <= tmp->next->val) {
newNode->next = tmp->next;
tmp->next = newNode;
return head;
}
tmp = tmp->next;
}
}
}
return head;
}
};
理解:
首先创建待插入的节点newNode,当head为空时,直接返回newNode即可。
由于我们需要返回原本的头节点,因此我们使用变量tmp转存head,并复用tmp来充当游标进行遍历。
我们先对链表进行一次完整遍历,获取链表的最值minV和maxV,由于链表是循环的,我们需要使用tmp->next != head作为我们循环的结束条件,含义为回到链表开头。
此时根据最大值和最小值是否相等(即整段链表值是否一致)来进行情况讨论:
- 若满足maxV=minV,此时目标节点newNode插入在哪个位置都满足条件,我们直接将其与head关联即可;
- 若不满足maxV=minV,此时我们先对链表进行一次遍历,找到有序链表的结束点(结束点的定义为:当前节点值为最大值,下一节点为最小值。即为有序链表分割位置的左端点),在根据『插入值insertval是否为新链表的最值』进行分情况讨论:
- 若满足x>=maxV或x<=minV,说明目标节点newNode插入分割位置即可
- 若不满足上述两条件,需要从分割位置出发,找到目标位置,即满足tmp->val<=x && x <= tmp->next->val的位置。
参考学习:力扣