1. 程式人生 > >用C++實現兩個元素相同但順序不同的等長陣列的正確匹配

用C++實現兩個元素相同但順序不同的等長陣列的正確匹配

《程式設計師面試寶典》第五版第96頁題目如下:

有兩等長陣列A,B,所含元素相同,但順序不同,只能取得A陣列某值和B陣列某值進行比較,比較結果為大於,小於,等於,但是不能取得同一陣列A或者B中兩個數進行比較,也不能取得某陣列中的某個值。寫一個演算法實現正確匹配(即A陣列中某值與B陣列中某值等值)。

最簡單的方法: 迴圈加判斷,複雜度O(n^2) 程式碼如下:

#include <iostream>
 
using namespace std;
 
void matching(int a[],int b[],int k)
{
int i = 0;
while(i <= k)
{
int j = 0;
while(j <= k)
{
if(a[i] == b[j])
{
cout << "(" << i <<"," << j <<")	";
break;
}
j++;
}
i++;
}
cout << endl;
}
 
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int b[10] = {10,6,4,5,1,8,7,9,3,2};
int k = sizeof(a)/sizeof(int);
matching(a,b,k);	
return 0;
}

一種優化方法: 利用二分法的思想,先取A0,與B0Bn-1比較,比較結果計入一個結構陣列C,結構為:{某數在B中的位置,標記,某數在A中的位置}。其中“標記”可為:大於,小於,等於。“某數在A/B中的位置”:0n-1,為相應位置。注:第一次比較後,C中元素都為{某數在B中的位置,標記,A0}格式。 取A1,由C可知B中與A0大小相同的數,與其比較。若A2大,則與B中比A0大的值比較。將比較結果替換計入結構陣列C。若A2小亦同理。 執行至完畢。 程式碼如下:

#define N 10

typedef struct {
	int loc_b;
	int flag;//-1,0,1分別表示b[loc_b]<,=,>a[loc_a]
	int loc_a;
}C;

C c[N];
int a[N];
int b[N];
//利用快排的思想和二分查詢的思想對陣列進行比較。利用a[0]初始化陣列c,其中陣列前半部分表示b[j]<a[0],後面部分表示b[j]>a[0].同時記錄k,使得b[k]==a[0],以後對a陣列進行比較時均與b[k]進行比較,(因為不讓同陣列之間進行比較).

void _match() {
	int head = 0;
	int tail = N - 1;
	int i, j, k;
	i = rand() % N;
	//初始化賦值
	for (j = 0;j<N;j++) {//類似與按照a[i]的值對b進行快排

		if (b[j]>a[i]) {//從後向前插入到c
			c[tail].flag = 1;
			c[tail].loc_a = i;
			c[tail].loc_b = j;
			tail--;
			continue;
		}
		if (b[j]<a[i]) {//從前向後插入到c
			c[head].flag = -1;
			c[head].loc_a = i;
			c[head].loc_b = j;
			head++;
			continue;
		}
		if (b[j] == a[i]) {
			k = j;//記錄相等時候的位置
		}
	}
	c[head].flag = 0;
	c[head].loc_a = i;
	c[head].loc_b = k;
	//endfor
	for (i = 0;i<N;i++) {
		if (a[i]<b[k]) {//a[i]小於b[k]時候,從c的前面進行比較
			for (j = 0;j<head;j++) {
				if (b[c[j].loc_b] == a[i]) {
					c[j].flag = 0;
					c[j].loc_a = i;
					break;
				}
			}
		}
		else if (a[i]>b[k]) {//從c的後面比較
			for (j = head + 1;j<N;j++) {
				if (b[c[j].loc_b] == a[i]) {
					c[j].flag = 0;
					c[j].loc_a = i;
					break;
				}
			}
		}

	}
}


int main() {
	int i = 0;
	for (i = 0;i<N;i++) {
		a[i] = i;
		b[i] = N - i - 1;
	}
	for (i = 0;i<sizeof(a) / sizeof(a[0]);i++)
		printf("%d  ", a[i]);
	printf("\n");
	for (i = 0;i<sizeof(b) / sizeof(b[0]);i++)
		printf("%d  ", b[i]);
	printf("\n");
	_match();
	for (i = 0;i<N;i++) {
		cout << "b[" << c[i].loc_b << "] match a[" << c[i].loc_a << "]" << endl;
	}
	system("pause");
	return 0;
}

進一步優化: 利用快速排序和二分法的思想。 1)在A陣列中隨機選取一個數,(根據題意,我們並不知道這個值的確定值是多少)比如說 A[i] ,然後和B 陣列中進行比較,根據你的資料結構,將B陣列每個數與A[i]進行比較,若比 A[i] 大的按照從後向前儲存,比 A[i] 小的從前向後儲存,要是等於A[i] ,就記錄下來 這個值在B的位置 j,繼續比較,直到B中陣列全部比較完成,然後再把這個相等的b[j] 插入空餘的那個中間位置上。 2) 然後再從A 陣列中取出數A[k]{k=0~n}與B[j](這個B[j] 就是A [i],因為同一陣列中不能比較大小,只能採用這種方式)比較,若比B[j]大,那麼從結構C中 A[i] 後面的比較,若比B[j]小,就從結構C中 A[i] 前面的比較,直到找到相等,然後更新結構陣列C 中與這個相等相應值。(注意,在這裡,只更新相等的那個數值的 “標記”,“某數在A中的位置”,其它與A[k]不相同,或大,或小的情況下,不更新,即還保持A[i] 的比較結果,以利於繼續比較) 3)重複步驟 2,繼續取A陣列 剩下的值,仍然與那個 B[j]比較,這樣逐步更新結構陣列C ,直到A陣列全部取出比較完,那麼這個程式也就完成了相應的功能。 隨機選擇A[i],要是選擇好,可以大大降低比較次數。