排序(4)

来源:互联网 发布:免费上网的软件 编辑:程序博客网 时间:2024/06/06 01:27

案例4
荷兰国旗问题。只包含0,1,2的整数数组进行排序,要求使用交换、原地排序,而不是利用计数进行排序。
分析:本题主要过程与快排划分过程类似。时间复杂度O(N),空间复杂度O(1)。
这里写图片描述
如图,一次检查,为0,就和首位交换,然后0区吃一个数;为2,就和末位交换,然后2区吃一个数。检查到二区域位置,整个过程结束。

#include<iostream>  #include<vector>using namespace std;  void out(vector<int> arr,int n){ //数组输出    for(int k=0;k<n;k++){          cout<<"arr["<<k<<"]:"<<arr[k]<<endl;      }  }void sort(vector<int> &arr, int length){    int k=length-1;//后面数组位置记录点    int temp;    int j=0;//前面数组位置记录点    for(int i=0;i<=k;i++){//i为当前点        if(arr[i]==0){            temp=arr[i];            arr[i]=arr[j];            arr[j]=temp;            j++;        }        if(arr[i]==2){            temp=arr[i];            arr[i]=arr[k];            arr[k]=temp;            k--;            i--;//关键点!!!!与后面数组交换时,位置点保持不动        }    }}int main(){    int num;    vector<int>arr;    cout<<"荷兰国旗"<<endl;    int n = 0;//n表示输入个数    while (cin >> num){          arr.push_back(num);         n++;         if(cin.get() == '\n')   //遇到回车,终止            break;                 }    sort(arr,n); //排序    out(arr,n);  //输出数组}  

案例5
在行列都排行序的矩阵中找数
0 1 2 5
2 3 4 7
4 4 4 8
5 7 7 9
若k为7,返回true;若k为6,返回false。
若矩阵为(m*n),该题最优解可以做到时间复杂度O(m+n),额外空间复杂度O(1)。
方法,从右上角找。
这里写图片描述
看5,5大于3,向左;
看2,2小于3,向下;
以此方法,找。找到,true。找到越界,false。

#include<iostream>  #include<vector>using namespace std;  bool sort(int **arr, int row,int line,int num){    int i=0;    int j=line-1;    while(i<row&&j>=0){        if(arr[i][j]>num){           j--;        }        else if(arr[i][j]<num){           i++;        }        else if(arr[i][j]==num){            cout<<i<<" "<<j;//若能找到,输出行列的位置            return true;         }    }    return false;   }int main(){    cout<<"请输入二维数组长和宽"<<endl;    int row,line;//定义行列    cin>>row>>line;    int **arr=new int*[row]; //根据行数动态分配数组行大小    for(int i=0;i<row;i++){        arr[i]=new int[line];//根据列数动态分配数组列大小    }    cout<<"请输入二维数组"<<endl;    for(int i=0;i<row;i++)        for(int j=0;j<line;j++)            cin>>arr[i][j];    cout<<"输出二维数组"<<endl;    for(int i=0;i<row;i++){        for(int j=0;j<line;j++)            cout<<arr[i][j]<<" ";        cout<<endl;    }    cout<<"请输入需要找的数"<<endl;    int num;    cin>>num;    bool result=sort(arr,row,line,num);    if(result==true)        cout<<"TRUE"<<endl;    else        cout<<"FALSE"<<endl;}  

案例6
需要排序的最短子数组长度
1 5 4 3 2 6 7
返回4,因为只有5 4 3 2需要排序。
该题最优解可以做到时间复杂度O(N),额外空间复杂度O(1)。
方法:从左向右遍历整个数组。
首先,从左向右遍历,记录最大值,只关系右边数比左边数小的这种情况。然后记录发生这种情况的最右位置。对此题,max=7,最右位置=2。
下从右往左遍历,记录最小值,和比其大的情况的最左位置。对此题,最左为5,min=1。最左最右位置中间的数就是需要排序的最短子数组

#include<iostream>  #include<vector>using namespace std;  void search(vector<int>arr, int length,int &max,int &right){    for(int i=1;i<length;i++){//从左向右遍历,寻找需排序数组的右边界        if(arr[i]>=max)            max=arr[i];         else            right=i;    }}void search2(vector<int>arr, int length,int &min,int &left){    for(int i=length-2;i>=0;i--){//从右向左遍历,寻找需排序数组的左边界        if(arr[i]<=min)           min=arr[i];        else            left=i;    }}int main(){    int num;    vector<int>arr;    int n = 0;//n表示输入个数    while(cin >> num){         arr.push_back(num);        n++;        if(cin.get() == '\n')   //遇到回车,终止           break;                 }    int max=arr[0];            int min=arr[n-1];    int left=20;      int right=20;   //左右边界初始值,任意给定,只要两个数相同,说明不需要排序    search(arr,n,max,right);//寻找需排序数组的右边界    search2(arr,n,min,left);//寻找需排序数组的左边界    if(left==right)        cout<<"不需要排序";    else        cout<<right-left+1;} 

案例7
给定一个整形数组arr,返回如果排序之后,相邻两数的最大差值。
例如:
1 2 3 4 7 8 9
最大是3,4 7之间
该题最优解可以做到时间复杂度O(N),额外空间复杂度O(N)。
思想来自桶排序。
解:随机数组
7 9 3 4 2 1 8
遍历一遍,得到min=1,max=9
总共7个数,分成7个桶。
这里写图片描述

这里写图片描述
不用考虑同一个桶的相邻数,只用考虑桶之间的相邻数。

#include<iostream>  #include<vector>#include<algorithm>using namespace std;  int sort(vector<int>arr, int n){     vector<vector<int>> B(n+1);//定义一个二维数组,用于记录每个桶的数,每个桶放两个值,最大值和最小值     int max,min,i,j,maxGap;     float k;     for(i=1,max=min=arr[0];i<n;i++){//记录数组最大值和最小值         if(arr[i]>max)            max=arr[i];         if(arr[i]<min)            min=arr[i];     }     float gap=1.0*(max-min)/n; //gap用来区分放入哪个木桶中,即桶的大小     for(i=0;i<n;i++){         k=(arr[i]-min)/gap;//很关键!!!先计算出值,在赋值给j(j为int型,四舍五入)         j=k;         if(B[j].empty()){ //若为空,该值同时赋给最大值和最小值            B[j].push_back(arr[i]);            B[j].push_back(arr[i]);         }         else{            if(B[j][0]>arr[i])               B[j][0]=arr[i];//刷新最小值            if(B[j][1]<arr[i])               B[j][1]=arr[i];//刷新最大值         }      }            for(i=j=0,maxGap=0;i<n;i=j)        {            while(B[i].empty())                i++;//若下个桶为空,就继续向下走            max=B[i][1];            j=i+1;            if(j<n+1)            {                while(B[j].empty())                    j++;                if(j>=n+1)                    break;                min=B[j][0];                if(min-max>maxGap)                    maxGap=min-max;            }        }           return maxGap;//输出结果}int main(){    int num;    vector<int>arr;    int n = 0;//n表示输入个数    while(cin >> num){         arr.push_back(num);        n++;        if(cin.get() == '\n')   //遇到回车,终止           break;                 }    int a=sort(arr,n);//计数排序    cout<<a;}