[路飞]_算法_链表_ 分割链表

129 阅读2分钟

题目描述

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

你不需要 保留 每个分区中各节点的初始相对位置。

 

示例 1:

image.png

输入: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 通过次数27,373提交次数

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

解题思路

直接利用重排列表的思想,把所有节点打散,再按照需求重新排列

  • 遍历链表,把节点都储存到数组中
  • 创建一个虚拟节点newNode作为要返回的重排的链表头部
  • 再遍历节点数组,把小于x的节点按照顺序,排在新链表后面
  • 再遍历一次链表,把大于等于x的节点排在新链表后面
  • 返回newNode.next

以上方法总共遍历3次,然后思考了下,优化成遍历两次

第一次不变,第二次和第三次同时进行

  • 思路就是,加入一个记录中间节点,中间节点定义为新链表中,最后一个小于x的元素,若没有,头部节点就是中间节点
  • 然后遍历的时候,小于x的节点往中间节点后面插图,并刷新中间节点
  • 大于等于x的元素直接往末尾插,并刷新记录的最后一个节点
  • 注意,当还没有遍历到过大于等于x元素的时候,最后一个节点就是中心节点,所以需要刷新最后一个节点

代码


/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} x
 * @return {ListNode}
 */
var partition = function(head, x) {
    let current=head;
    let list=[];//储存节点
    while(current){
        list.push(current);
        current=current.next;
    }
    let result=new ListNode(0,null);
    let lastNode=result;
    let centerNode=lastNode;
    let isMore=false;
    for(let i=0;i<list.length;i++){
        list[i].next=null;
        if(list[i].val<x){
            //小于x的节点插入分割节点后面
            let next=centerNode.next;//保存原本的next节点
            centerNode.next=list[i];//添加到分隔节点后
            centerNode=list[i];//刷新中间节点
            centerNode.next=next;//把原本的next节点放到现在的节点后面,实现中间插入节点
            if(!isMore){
                //如果从没遍历到过大于x的元素,则lastNode就是centerNode
                lastNode=centerNode;//记录新链表的末尾
            }
        }else{
            //大于x的节点插入链表末尾
           lastNode.next=list[i];//添加到新链表的末尾
            lastNode=list[i];//记录新链表的末尾
            isMore=true;
        }
  
    }

    return result.next;

};