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