PartitionList

简而言之,就是linklist的partition函数,没错快排用到的partition,于是想里面for后移用next,只是swap要注意一下,
于是我写了一个node->val交换的swap,因为这个是左值,所以可以调用C++11的引用交换的swap,但是发现WA了,后来仔细看题,发现居然
要稳定的排序,这,快排本身这种跳跃交换就是不稳定的,我就觉得很蛋疼,后来想想终于明白为啥要加稳定排序这个要求了,我a[j]>=x的话,直接后面加,
不交换肯定稳定,但是如果交换,有跳跃,那么主要是a[i+1]要交换到>=x区间的最后一个,因此导致原来的a[i+1]不能保持和已排序的>=x里的数
稳定的关系,但是linklist不是可以有高效插入这种性质么?直接把a[j]查到a[i] a[i+1]不就可以了,于是终于明白之前Qsort的linklist其实严格意义不算正确,
因为还是基于数的交换,于是开始写逻辑。

但是发现逻辑不好全部写对。要记录inext,jnext,jprev, 等等,还要处理一堆特殊情况。先把一般的写下,但是发现lumoto的partition会有子交换,
这种对于swap当然很好解决,但是linklist很蛋疼,我模拟一遍结束发现结果乱七八糟的,也没分析出原因,于是开始单独处理一下,其实子交换就是
不用动了o(╯□╰)o指针改next的next就是了。

但是发现还是挂了,[2,1] 2这个case,后来模拟一遍,发现head丢了,于是分析什么情况会丢head,其实也就是第一个数>=x的时候,只有这种情况,否则的话,后面j都是插入到第i i+1之间的,其中i>=1
所以不可能会丢head,好,那么什么时候会丢head,也即后面第一次a[j]<x的时候,而此时i=headprev始终没有修改过,于是就那这个来判断,然后j没有改之前的值为新的head,好分析完了,基本case都
OK了。

我猜会有逻辑更漂漂的代码,至少我这条路走到出口不是很漂漂,正如编程之美上一样,一开始写个代码,然后面试官温格case,挂,改,问个case,挂,改这样loop几次,然后过了,于是我挂了。。。。

体会到linklist潜在的威力了!!

ListNode partition(ListNode head, int x) {
ListNode headprev=new ListNode(0);
headprev->next=head;
ListNode
i=headprev, inext, jnext, jprev=headprev;
for(ListNode
j=head;j!=NULL;j=j->next)
{
if(j->valnext!=j)
{
jnext=j->next,inext=i->next;
if(i==headprev)
head=j;
i->next=j;
j->next=inext;
jprev->next=jnext;
j=jprev;
i=i->next;
}
else
i=i->next;
//int tmp=i->val;
//i->val=

            //swap(i->val,j->val);

        }
        jprev=j;
    }
    delete headprev;
    return head;
}

Posted by richard爱闹 - 7月 25 2014
如需转载,请注明: 本文来自 Richard