剑指 Offer II 029. 排序的循环链表

给定一个循环单调非递减的链表,编写一个函数在列表中插入一个新元素,保持列表仍是循环升序。详细介绍了特殊情况处理、解题思路和完整代码实现。
摘要由CSDN通过智能技术生成

剑指 Offer II 029. 排序的循环链表

原题

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

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

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

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

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

剑指 Offer II 029. 排序的循环链表

解题思路

先考虑特殊情况: 链表为空。此时需要新创建一个结点,并将其指向自己。

现在来分析一般的情况。

由于给定的链表是循环单调非递减列表

我们设该链表的尾结点存储的是列表最大值, 链表的头结点存储的是列表最小值

除了 尾结点 -> 头结点 这个连接是递减的, 其他的连接都是非递减的。为了保持插入新结点后,还是这样的顺序,我们就必须分析下结点应当插入的位置。

在一般情况里, 可以根据 insertVal 的值分成以下三种情况。

序号insertVal 与链表所有元素值相比插入位置
1最小循环链表结点
2最大循环链表结点
3既不是最大,也不是最小左结点 L, 右结点 R 的中间
  1. 第一、二种情况:由于 insertVal 找不到比其小的/大的结点, 所以为了保持非递减,将 insertVal 作为新的头结点/尾结点
  2. 第三种情况:存在 L.val <= insertVal && R.val >= insertVal, 因此插入中间能保持非递减顺序。

我们至多遍历一圈链表, 枚举出所有可能的 L, R。

假如遍历完后, 只存在 R/L, 说明 insertVal 属于 (最大/最小)。

否则, insertVal 既不是最大, 也不是最小。

完整代码

class Solution {
		public Node insert(Node head, int insertVal) {
			// 特殊情况, 链表为空
			if (head == null) {
				Node n = new Node(insertVal);
				n.next = n;
				return n;
			}
            
			Node L = null;
			Node R = null;
			Node last = head;
			Node next;
			Node temp = head;
            // temp 必须走过两次 head
            // 第一次是枚举作为 L 结点的时候
            // 第二次是枚举作为 R 结点的时候
            // 以此保证枚举过所有的 L, R 结点
			int count = 2;
			while (count != 0) {
				if (temp == head) {
					--count;
				}
				if (temp.val >= insertVal) {
					R = temp;
				} else {
                    // 出现 L 结点, 则需要将之前的 R 结点重置
					L = temp;
					R = null;
				}
				if (L != null && R != null) {
					break;
				}
				next = temp.next;
				if (temp.val > next.val) {
					last = temp;
				}
				temp = next;

			}
			
			if (L == null || R == null) {
				next = last.next;
				last.next = new Node(insertVal, next);
			} else {
				L.next = new Node(insertVal, R);
			}
			return head;
		}
	}

其他

本题解同步至剑指offer专项突击版仓库内, 欢迎查看。

我的力扣主页

Github仓库

Gitee仓库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值