LeetCode [86]分隔链表

题目描述

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

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

示例:

输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5

题目分析

这道题有点难懂,以我自己的理解来看,就是找到比x小的,那么我放前面去,比他大的就留原地。不需要按照大小给链表排序。这样就可以创建两个链表,一个保存遍历到比x小的值,另一个就保留原地保存到另一个链表,最后将这两个链表连接起来就行。

源码

/**
* Definition for singly-linked list.
* public class ListNode {
*     int val;
*     ListNode next;
*     ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode partition(ListNode head, int x) {
    ListNode head1 = new ListNode(0);
    ListNode head2 = new ListNode(0);
    ListNode node1 = head1;
    ListNode node2 = head2;
    //两个链表
    while (head != null){
        if (head.val<x){
        //小于就保存在node1里
            node1.next = head;
            head = head.next;
            node1 = node1.next;
            node1.next = null;
        }else {
        //大于等于的到node2里,不需要排序
            node2.next = head;
            head = head.next;
            node2 = node2.next;
            node2.next = null;
        }
    }
    node1.next = head2.next;
    //最后连起来
    return head1.next;
}
}

改进

还有一种方法那就是在原地交换顺序,先找到小于x的最后一个节点,然后当碰到大于等于x的节点时,交换一下顺序。当遍历完时就已经换好了,有点像是双指针的感觉。

改进代码

class Solution {
public ListNode partition(ListNode head, int x) {
    ListNode firstNode=new ListNode(Integer.MIN_VALUE);//head前加一个节点
    firstNode.next=head;
    ListNode pNode=firstNode;
    while(pNode.val<x && pNode.next!=null && pNode.next.val<x){//找到连续小于x的最后一个pNode
        pNode=pNode.next;
    }
    ListNode y=pNode;
    while(y.next!=null){//找到需要插到前面的节点y.next
        if(y.next.val<x){//插到pNode后面,更新pNode,并且将y.next前后连接起来.
            ListNode temp1=pNode.next;
            ListNode temp2=y.next.next;
            pNode.next=y.next;
            y.next.next=temp1;
            pNode=y.next;
            y.next=temp2;
        }
        else{
            y=y.next;
        }
    }
    return firstNode.next;
}
}

分析

第一个时间复杂度为O(n)
第二个就是O(n),空间的复杂度第一个要高一点,因为创建了新的地址。

难点

遇到链表题,令人头疼的就是要考虑到两个数据之间的连接。如果没有空间的限制的话,用分治法的思想就很好。

小结

在不限制空间的情况下,不管是交换顺序还是排序,分治思想是一个很好的办法,具体可以模仿快速排序的做法。
[1]https://leetcode-cn.com/problems/partition-list/submissions/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值