【算法-LeetCode】86. 分隔链表(链表;指针)

86. 分隔链表 - 力扣(LeetCode)

文章更新:2021年10月22日20:42:55

问题描述及示例

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

示例 2:
输入:head = [2,1], x = 2
输出:[1,2]

提示:
链表中节点的数目在范围 [0, 200] 内
-100 <= Node.val <= 100
-200 <= x <= 200

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解

链表的题往往要用到指针的思想,这句话我说过好几次了,目前我做的好几道链表题都是用各种指针来标识节点和辅助遍历之类的。这里的所谓指针其实就是一个保存节点对象内存地址的一个变量

这道题也是一样的套路,也是用指针来保存节点地址和辅助遍历链表。其中 p 指针用于遍历链表。deleted 指针则是用于标识要从原链表中删除的节点。而 rear 指针则用于标识 lessThanX 链表的尾部。

大体思路如下:

  1. 先创建一个辅助链表 lessThanX 用于按序存储那些节点值小于 x 的节点。
  2. p 指针遍历链表,如果当前遍历的节点的节点值小于 x ,则将该节点从链表中暂时删除,并用一个 deleted 指针保存这个节点。
  3. 将上述被删除的节点链接到 lessThanX 链表的尾部。
  4. 原链表遍历完成后,lessThanX 中就存储了那些节点值小于 x 的节点。而且这些节点的相对位置和其在原链表的相对位置是一样的。
  5. 将原链表的剩余节点链接到 lessThanX 链表的尾部即可。

注意,因为涉及到要从链表中删除一个节点,所以遍历原链表时,p 指针指向的是当前遍历节点的前一个节点。

而且,为了方便表示,我给原链表和辅助用的 lessThanX 链表都加上了一个辅助头节点。

详解请看下方注释:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} x
 * @return {ListNode}
 */
var partition = function(head, x) {
  // dummy是给原链表加的辅助头节点
  let dummy = new ListNode(0, head);
  // lessThanX是用于存储节点值小于x的节点的辅助链表,
  // 其中lessThanX也可以看做是该链表的辅助头结点
  let lessThanX = new ListNode(0, null);
  // rear用于标识lessThanX的表尾,方便我们给它添加节点
  let rear = lessThanX;
  // p指针用于遍历原链表,其初始指向为辅助头结点dummy,
  // 但是因为我们遍历的当前节点为p.next,所以实际上遍历的起点为原链表的头节点
  let p = dummy;
  // deleted用于标识要从原链表中删除的节点
  let deleted = null;
  // 如果当前遍历节点不为空,则继续往下遍历
  while(p.next) {
    // 如果当前遍历节点的节点值小于x,
    if(p.next.val < x) {
      // 则让deleted指针标识该节点
      deleted = p.next;
      // 改变p指针所指向的节点的next域已达到从原链表中删除当前遍历节点的效果
      p.next = p.next.next;
      // 设置当前节点的next域为空
      deleted.next = null
      // 将被删除的节点链接到lessThanX的尾部
      rear.next = deleted;
      rear = rear.next;
      // 因为有一个节点被从原链表中删除了,所以出现了类似数组塌陷的效果,
      // 此时应该立即进入下一次遍历
      continue;
    }
    // 如果当前遍历节点的节点值大于等于x,则让该节点保持原位,开始下一次遍历
    p = p.next;
  }
  // 当原链表被遍历完后,lessThanX中存储的节点的节点值就是小于x的
  // 将原链表剩余的节点链接到lessThanX中的尾部
  rear.next = dummy.next;
  // 将重新拼接后的链表返回,注意不要包含辅助头结点
  return lessThanX.next;
};


提交记录
168 / 168 个通过测试用例
状态:通过
执行用时:72 ms, 在所有 JavaScript 提交中击败了77.13%的用户
内存消耗:39.1 MB, 在所有 JavaScript 提交中击败了79.60%的用户
时间:2021/10/22 20:57

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年10月22日20:48:13

参考:分隔链表 - 分隔链表 - 力扣(LeetCode)

【更新结束】

有关参考

暂无

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值