zoukankan      html  css  js  c++  java
  • luogu_P1177 【模板】快速排序 (快排和找第k大的数)

    【算法】

      选取pivot,然后每趟快排用双指针扫描(l,r)区间,交换左指针大于pivot的元素和右指针小于pivot的元素,将区间分成大于pivot和小于pivot的

    【注意】

      时间复杂度取决于pivot的选取是否能把(l,r)区间分成长度相等的两个子区间。

      最优:O(nlogn)  最差:O(n2)

      问题解决:

    1. 版本一:pivot选择区间中间的元素可以解决数组本身就已经排好序的问题,但是无法解决数组中每个元素均相等(第五个点tle)
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e5;
     4 int n,p,i,j;
     5 int a[maxn];
     6 void quick_sort(int l,int r)
     7 {
     8     if(l>r) return;
     9     i = l, j = r;
    10     //swap(a[l], a[(l+r)>>1]); ------pivot选区间中间的元素
    11     while(i < j) {//i和j相等时停下来
    12         while(a[j]>=a[l] && i < j) j--; //先右再左很关键!若右指针和左指针相遇则此时左指针指向pivot或小于pivot的元素(前一次有交换),若左指针和右指针相遇,则此时
    13         while(a[i]<=a[l] && i < j) i++; //右指针应当已经寻找到的小于pivot的元素;若先左再右,则反过来了。pivot的位置会出错。
    14         if(i<j) swap(a[i],a[j]);
    15     }
    16     swap(a[l],a[j]);
    17     quick_sort(l,i-1);
    18     quick_sort(i+1,r);
    19 }
    20 int main()
    21 {
    22     cin>>n;
    23     for(int i = 1; i <= n; i++)
    24         cin>>a[i];
    25     quick_sort(1,n);
    26     for(int i = 1; i <= n; i++)
    27         cout << a[i] << " ";
    28     return 0;
    29 }

        2、版本二:先判断是否有序,若有序则结束,若无序再按原方法。

        3、版本三:每次分成两个子区间,左区间小于等于pivot,右区间大于等于pivot,但不一定确定好pivot的位置,但最终区间长度为2或3的时候必定能确定好

            ------------------------感觉这种要好写一点,理解了之后,其实都是细节------------------------

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e5;
     4 int n,p,i,j;
     5 int a[maxn];
     6 void quick_sort(int l,int r)
     7 {
     8     int pivot = a[(l+r)>>1]; 
     9     i = l, j = r;
    10     while(i <= j) { //直到i>j为止,就算数组元素均相等也会向前推进
    11         while(a[i] < pivot) i++; 
    12 while(a[j] > pivot) j--; 13 if(i <= j) { 14 swap(a[i],a[j]); 15 i++, j--; 16 } 17 } 18 if(i < r) quick_sort(i,r); 19 if(j > l) quick_sort(l,j); 20 } 21 int main() 22 { 23 cin>>n; 24 for(int i = 1; i <= n; i++) 25 cin>>a[i]; 26 quick_sort(1,n); 27 for(int i = 1; i <= n; i++) 28 cout << a[i] << " "; 29 return 0; 30 }

        4、找第k大的数:分治法类似快排的方法,平均复杂度O(n)【1+2+4+。。。+n/2+n】按版本三的话不太好写,就按版本一来吧:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e5;
     4 int n,k,i,j;
     5 int a[maxn];
     6 int quick_find(int l,int r,int k)
     7 {
     8     int pivot = a[(l+r)>>1], rec = 0;
     9     i = l, j = r;
    10     swap(a[(l+r)>>1], a[l]);
    11     while(i < j) {
    12         while(a[j] >= pivot && i < j) j--, rec++;
    13         while(a[i] <= pivot && i < j) i++;
    14         if(i < j) swap(a[i],a[j]);
    15     }
    16     swap(a[i],a[l]);
    17     if(k == rec + 1) return a[i];
    18     else if(k <= rec) return quick_find(i+1,r,k);
    19     else return quick_find(l, i-1, k-rec-1);
    20 
    21 }
    22 int main()
    23 {
    24     cin>>n>>k;
    25     for(int i = 1; i <= n; i++)
    26         cin>>a[i];
    27     cout<<quick_find(1,n,k)<<endl;
    28     return 0;
    29 }

     

  • 相关阅读:
    进度条
    html5 表单新增事件
    html5 表单的新增type属性
    html5 表单的新增元素
    html5 语义化标签
    jq 手风琴案例
    codeforces 702D D. Road to Post Office(数学)
    codeforces 702C C. Cellular Network(水题)
    codeforces 702B B. Powers of Two(水题)
    codeforces 702A A. Maximum Increase(水题)
  • 原文地址:https://www.cnblogs.com/Willendless/p/9310090.html
Copyright © 2011-2022 走看看