1 給定兩個已經排序好的數組A,B,A足夠大,把兩個數組重新合併成A的有序數組
2 給定一個存放整數的數組,重新排列數組使得數組左邊爲奇數,右邊爲偶數 :空間複雜度是1,時間複雜度是n
3 找出數組裏大於等於左側、小於等於右側的所有數
4 給定 幾個數字,寫出來全排列 ,如1234
===============================================================================
1 給定兩個已經排序好的數組A,B,A足夠大,把兩個數組重新合併成A的有序數組
思路:
1 從最大(A和B的最後進行比較,把最大的元素放到最後面,之後--)
2 結束條件:只剩下A的元素了,或者只剩下B的元素之後複製到A的對應位置就可以了。
void printArray( int * arrA, int n ) { if(arrA==NULL||n<=0) return; cout<<endl; for(int i=0;i<n;i++) { cout<<arrA[i]<<" "; } }
int * MergerArray( int *arrA,int sizeA,int *arrB,int sizeB ) { //第一種方法:從最後的一個元素開始比較,從後往前 移動元素。: 就地 進行排序 if(arrA==NULL||arrB==NULL||sizeA<0||sizeB<0) return NULL; int posA=sizeA-1,posB=sizeB-1; //posA+posB-1 爲當前的合併的元素的下標 while(posA>=0&&posB>=0) { if(arrA[posA]>arrB[posB]) { arrA[posA+posB+1]=arrA[posA]; posA--; } else { arrA[posA+posB+1]=arrB[posB]; posB--; } } //退出循環的兩種情況:1 只剩下arrA的元素(不用管了(posB<0)),2 只剩下arrB的元素(posA<0) while(posB>=0) { arrA[posA+posB+1]=arrB[posB]; posB--; } /*copy(arrA, arrA + sizeA+sizeB-1, ostream_iterator<int>(cout, " ")); */ printArray(arrA,sizeA+sizeB); return arrA; }
測試代碼
int arrayA[10] = {11, 21, 25, 37, 49}; int arrayB[] = {2, 4, 6, 28, 100}; int sizeB = sizeof (arrayB) / sizeof *(arrayB); int sizeA = sizeof (arrayA) / sizeof *(arrayA) - sizeB; MergerArray(arrayA,sizeA,arrayB,sizeB);
2 給定一個存放整數的數組,重新排列數組使得數組左邊爲奇數,右邊爲偶數 :空間複雜度是1,時間複雜度是n
思路:其實就是 要求原地進行交換之類的-----每一趟(在while循環裏,成對出現low和high)
1 可以是兩頭標記(low標記偶數,high標記奇數,結束low=high
2 可以是 從頭開始標記(even標記偶數在前,odd標記奇數在後,之後交換,知道最後爲止)
測試代碼
int arr[]={1,2,3,4,5,11,6,7,8,9}; int n=sizeof(arr)/sizeof(int); reArray(arr,n);
void reArray( int *arr,int n ) { ////方法1 //printArray(arr,n); //int low=0,high=n-1; //while(low<high) // while(low<=high)多交換一次:注意邊界條件 //{ // while(low<high&&arr[low]%2!=0) //左邊找到偶數 // { // low++; // } // while(low<high&&arr[high]%2==0) //右邊找到奇數 // { // high--; // } // swap(arr[low],arr[high]); // printArray(arr,n); //} //printArray(arr,n); //方法2: todo:如果要求 偶數和奇數的相對位置不變,該怎麼辦??? printArray(arr,n); int low=0,high=0; while(low<n&&high<n) { while(low<n&&arr[low]%2!=0) //找到偶數 { low++; } high=low; //要交換的奇數必須要在偶數的右邊 才符合情況。 while(high<n&&arr[high]%2==0) //找到奇數 { high++; } if(low<n&&high<n) //不判斷的話,可能會發生過界的情況 或者在上面的 判斷條件加上 low=n-1 { swap(arr[low],arr[high]); } printArray(arr,n); } printArray(arr,n); }
3 找出數組裏大於等於左側、小於等於右側的所有數
思路:提前對數組進行處理 leftmax,rightmin arr[i]與其進行比較
掃描一趟歸併: max[i] =max(max[i-1],arr[i]),對於初始化 max[0]=arr[0];
int array[] = {3, 1, 2, 5, 8, 6, 10,11};
const int size = sizeof array / sizeof *array;
//使用動態數組保存要 得到的結果(結果是幾個不知道) void reArray2( int *arr,int n,vector<int> &result ) { //以空間 換時間:每一個i對應 leftmax[i]和rightmin[i]:一趟掃描最大值和最小值 //對應的是:有 [i-1]推導出[i] printArray(arr,n); //作爲測試來用的。 int maxLeft[size]; int minRight[size]; maxLeft[0]=arr[0]; minRight[n-1]=arr[n-1]; for(int i=0;i<n;i++) { maxLeft[i]=maxLeft[i-1]>arr[i]?maxLeft[i-1]:arr[i]; //max(maxLeft[i-1],arr[i]) } for(int i=n-1;i>=1;i--) { minRight[i-1]=minRight[i]<arr[i-1]?minRight[i]:arr[i-1]; //min(minRight[i],arr[i-1]) } for(int i=0;i<n;i++) { if(arr[i]>=maxLeft[i]&&arr[i]<=minRight[i]) { /*cout<<arr[i]<<endl;*/ result.push_back(arr[i]); } } copy(result.begin(), result.end(), ostream_iterator<int>(cout, " ")); }
4 給定 幾個數字,寫出來全排列 ,如1234
思路:全排列的問題:交換→遞歸→最次還原(交換)
還要繼續學習呀: STL系列之十 全排列(百度迅雷筆試題)
void Perm(int *array, int pos, int size ) { assert(array!=NULL); if(pos==size) { copy(array, array + size+1, ostream_iterator<int>(cout, " ")); cout <<"本次全排列完畢!" <<endl; } else { for(int i=pos;i<=size;i++) { //在這裏可以使用 if語句減少重複數值的判斷。if(arr[i]==arr[pos]比較是否相等) swap(array[i],array[pos]); Perm(array,pos+1,size); swap(array[i],array[pos]); } } }