排序(4)

案例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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章