持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
一.题目:
剑指 Offer II 029. 排序的循环链表 给定循环单调非递减列表中的一个点,写一个函数向这个列表中插入一个新元素
insertVal,使这个列表仍然是循环升序的。
给定的可以是这个列表中任意一个顶点的指针,并不一定是这个列表中最小元素的指针。
如果有多个满足条件的插入位置,可以选择任意一个位置插入新的值,插入后整个列表仍然保持有序。
如果列表为空(给定的节点是 null),需要创建一个循环有序列表并返回这个节点。否则。请返回原先给定的节点。
示例 1:
输入:head = [3,4,1], insertVal = 2
输出:[3,4,1,2]
解释:在上图中,有一个包含三个元素的循环有序列表,你获得值为 3 的节点的指针,我们需要向表中插入元素 2 。新插入的节点应该在 1 和 3 之间,插入之后,整个列表如上图所示,最后返回节点 3 。
示例 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
二、思路分析:
老规矩,一上来就需要抽取题目的关键信息,题目的诉求是给定一个循环单调非递减列表,我们需要向这个列表插入一个新元素,使得这个列表仍然是循环升序的,首先我们需要明白,题目给定的指针很有可能不是指向的最小的位置,而是需要我们自己去寻找位置进行插入,所以这道题需要分情况进行讨论:
- 首先如果列表为空的话,我们插入的指针需要自己形成一个循环链表;
- 如果不为空的话需要在进行讨论,如果只有一个元素,我们直接选择位置进行循环即可;
- 如果插入的是一个多元素的列表,我们需要进行
遍历寻找合适的插入点,如果遍历的位置它的值和它下一位置的值正好是跟插入值形成升序的话,直接跳出循环进行插入操作; - 如果刚好插入的是
最大值与最小值的位置,则也需要跳出循环进行插入操作,因为题目给定的是升序链表,所以如果出现下一位置的是比上一位置的小的话证明就是链表的头尾。
三、代码:
/**
* Definition for node.
* class Node {
* val: number
* next: Node | null
* constructor(val?: number, next?: Node) {
* this.val = (val===undefined ? 0 : val);
* this.next = (next===undefined ? null : next);
* }
* }
*/
function insert(head: Node | null, insertVal: number): Node | null {
const insVnode = new Node(insertVal, undefined);
if(head == null){
insVnode.next = insVnode;
return insVnode;
}
let node = head;
while(node.next != head){
if(node.val <= insertVal && insertVal <= node.next.val){
break;
}
if(node.val > node.next.val && (node.val <= insertVal || insertVal <= node.next.val)){
break;
}
node = node.next;
}
insVnode.next = node.next;
node.next = insVnode;
return head;
}
四、总结:
这道题主要考察我们的细心,其实用的算法不是很难,就是
插入+遍历,但是如果你没有把所有情况考虑在内的话,做出来的答案可能就是错的没有考虑完全。