1. 程式人生 > >快排思想求解第k小

快排思想求解第k小

思路1:基於快排每次都會確定一個最終元素位置,下面程式碼則採用這種思想編寫。

思路2:同樣基於快排,每次劃分後看左邊區間元素個數是否大於k個,若左邊區間元素個數大於k個則在左區間找第k大元素,若左邊區間個數小於k個,這時假設左邊有len個元素,這時候在右邊區間找第k-len+1個即可。

注:有不正當地方歡迎指出!

程式碼:

/*
快排思想求第k小,時間複雜度O(n),空間O(1)
測試資料:
5 3
2 1 3 5 4
5 3
1 2 3 1 4
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int a[maxn];
int ans,n;
int partion(int l,int r)
{
    int i=l,j=r;
    int temp=a[l];
    while(i<j)
    {
        while(i<j&&a[j]>=temp) j--;
        if(i<j) a[i]=a[j];
        while(i<j&&a[i]<=temp) i++;
        if(i<j) a[j]=a[i];
    }
    a[i]=temp;
    return i;//返回每次劃分元素位置
}
int quickSort(int l,int r,int k)
{
    int mid=partion(l,r);
    if(mid==k) return a[k];
    if(mid>k)
        return quickSort(l,mid-1,k);
    if(mid<k)
        return quickSort(mid+1,r,k);

}
int main()
{
    int k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        ans=0;
        for(int i=1; i<=n; i++) scanf("%d",&a[i]);
        ans=quickSort(1,n,k);
        printf("%d\n",ans);
    }
    return 0;
}

下面依照上面思想O(n)將一個數組劃分為這樣的兩個集合:設集合A元素個數為n1,集合內元素和為sum1,集合B元素個數為n2,集合內元素和為sum2,兩集合滿足|n1-n2|儘可能小的前提下|sum1-sum2|儘可能大。

程式碼:

/*
時間複雜度O(n),空間O(n)
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int a[maxn],A[maxn],B[maxn];
int n;
int Partion(int l,int r)
{
    int i=l,j=r;
    int temp=a[l];
    while(i<j)
    {
        while(i<j&&a[j]>=temp) j--;
        if(i<j) a[i]=a[j];
        while(i<j&&a[i]<=temp) i++;
        if(i<j) a[j]=a[i];
    }
    a[i]=temp;
    return i;
}
void quickSort(int l,int r,int k)
{
    int mid=Partion(l,r);
    if(mid==k)
    {
        for(int i=1;i<mid;i++) A[i]=a[i];
        for(int i=mid;i<=n;i++) B[i]=a[i];
        return;
    }
    if(mid>k)  quickSort(l,mid-1,k);
    if(mid<k)  quickSort(mid+1,r,k);
}
int main()
{
    int k;
    while(scanf("%d",&n)!=EOF)
    {
        if(n%2==0) k=(n>>1)+1;
        else       k=(n+1)>>1;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        quickSort(1,n,k);
        for(int i=1;i<k;i++) printf("%d ",A[i]);
        printf("\n");
        for(int i=k;i<=n;i++) printf("%d ",B[i]);
        printf("\n");
    }
    return 0;
}