算法进阶指南—特殊排序

题意:有N个数,每两个数之间的大小关系要通过询问来得知,但是每个数之间的大小关系不具有传递性,比如 a<b  ,  b< c不一定有a<c。

现在问你能否在10000次询问内把这N个数排成一列,使得相邻两个数,左边比右边小。

思路:把前  i - 1个数字排好序后,第  i  个数字应该插入到什么位置,则二分前面  i - 1 的有序序列,利用中间值mid 来判定i的插入位置。

判定方法,若mid< i 则mid 右半边是合法的,另 l = mid,若mid >i,则 mid 左半边是合法的,另 r= mid-1;

找到插入位置r后把  i  插入到最后一个位置,把 i 从最后一个位置一直换到第r+1个位置,然后再判断它与 r的关系若小于r,把 r 与r+1位置上的数对换。

前i-1个排序运用了插入排序,每插入一个新的数都用二分的方法取判定它的位置。最后由于每次二分判定位置次数最多为n*log n.所以两个数比较大小的询问也最多提出n*log n次。

加起来总共为 2*log n+3*log n+........+n*log n 其小于10000次

下面上代码:

class Solution {
public:
    vector<int> specialSort(int N) {
        vector<int> res;
        res.push_back(1);
        for(int i=2;i<=N;i++)
        {
            int l=0,r=res.size()-1;
            while(l<r)
            {
            int    mid=(l+r+1)>>1;
                if(compare(res[mid],i))
                l=mid;
                else
                r=mid-1;
             }
             
             res.push_back(i);
             for(int j=res.size()-2;j>r;j--)
             swap(res[j],res[j+1]);
             if(!compare(res[r],res[r+1]))
             swap(res[r],res[r+1]);      
         } 
        return res;      
        
    }
};
原文地址:https://www.cnblogs.com/rainyskywx/p/10349571.html