【數據結構】順序錶王道綜合題

首先是大概的一個框架,然後重點說的是第12題。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
typedef struct LNode{
	int data[100];
	int length;
}SqList;

int n,m;
void InitList(SqList &L){						//構造順序表 
	int i;
	cin >> n;
	for(i=0;i<n;i++)
		cin >> L.data[i];
	L.length=n;
}
void Trave(SqList &L){							//遍歷順序表 
	int i;
	for(i=0;i<L.length;i++)
		cout << L.data[i] << " ";
	cout << endl;
	cout << "The Length is "<< L.length <<endl;
} 
void Reverse(SqList &L,int left,int right){		//逆置函數 ,從left處到right處的逆置
	int i,num;
	for(i=left;i<=(right-left)/2;i++){
		num=L.data[right-i];
		L.data[right-i]=L.data[i];
		L.data[i]=num;
	}
	return ;
}

int main()
{
	SqList L;
	SqList La,Lb;
	while(true){
		InitList(L);
		//Trave(L);
		//InitList(La);
		//Trave(La);
		//f6(L);
		//f7(L,La);
		//Lb=f7(L,La);
		//Trave(Lb);
		//f8(L);
		//Trave(L);
		//f9(L,9);
		//f12(L); 
		//cout << f12(L) << endl;
		Trave(L);	
	}
	return 0;
}

下面是一些題目的函數:

void f6(SqList &L){						//刪除有序表中的重複元素 
	int i,k=0;
	for(i=1;i<L.length;i++){
		if(L.data[k]!=L.data[i]){
			k++;
			L.data[k]=L.data[i];
		}
	}
	L.length=k+1;
}
SqList f7(SqList &La,SqList &Lb){		//合併兩個有序表 
	SqList L;
	int i,j,k=0;
	for(i=0,j=0;i<La.length,j<Lb.length;){
		if(La.data[i]>=Lb.data[j]){
			L.data[k++]=Lb.data[j];
			j++;
		}
		else if(La.data[i]<Lb.data[j]){
			L.data[k++]=La.data[i];
			i++;
		}
	}
	if(i<La.length){
		for(;i<La.length;i++){
			L.data[k++]=La.data[i];
		}
	}
	else if(j<Lb.length){
		for(;j<Lb.length;j++){
			L.data[k++]=Lb.data[j];
		}
	}
	L.length=k;
	return L;
}
void f8(SqList &L){			//順序表L=(La,Lb)處理後L=(Lb,La) 
	int n,m;
	cin >> n >> m;
	Reverse(L,0,n+m-1);
	//Trave(L);
	Reverse(L,0,n-1);
	Reverse(L,n,n+m-1);
} 
void f9(SqList &L,int x){			//O(n) 查找元素x然後與後面節點交換數值
	int i,j,k=0;					//找不到的時候插入到有序表中
	for(i=0;i<L.length;i++){
		if(L.data[i]==x&&i!=L.length-1){
			L.data[i]=L.data[i+1];
			L.data[i+1]=x;
			return ;
		}
		if(L.data[i]>x){
			for(j=L.length;j>i;j--)
				L.data[j]=L.data[j-1];
			L.data[j]=x;
			L.length++;
			return ;
		}
	}
} 
int f11(SqList &La,SqList &Lb,int n){	//找到兩個升序列合併之後的中位數 
	int s1=0,d1=n-1,m1;
	int s2=0,d2=n-1,m2;
	while(s1!=d1||s2!=d2){			//時間複雜度O(log2n)
		m1=(s1+d1)/2;
		m2=(s2+d2)/2;
		if(La.data[m1]==Lb.data[m2])			//兩個序列的中位數相等的時候直接退出 
			return La.data[m1];
		if(La.data[m1]>Lb.data[m2]){			//主要是二分的思想逐漸折半然後比較
			if((s1+d1)%2==0){
				s1=m1;
				d2=m2;
			}
			else{
				s1=m1+1;
				d2=m2;
			}
		}
		if(La.data[m1]<Lb.data[m2]){
			if((s2+d2)%2==0){
				d1=m1;
				s2=m2;
			}
			else{
				d1=m1;
				s2=m2+1;
			}
		}
	}
	return La.data[s1]<Lb.data[s2]?La.data[s1]:Lb.data[s2];
} 

第12題:【2013年統考題】找到到順序表中的主元素,主元素的定義爲出現的次數m>n/2,其中n是整個表的長度。
思考:
這個題目我最先想的是統計各個整數出現的個數,找到出現次數最多的數就時候選主元素。統計的話需要佔用空間O(n),時間上只要跑兩遍就可以了,第一遍統計第二遍比較多少,時間複雜度也是O(n)。但是參考答案只需要O(1)的空間複雜度,就是直接找候選主元素。
思路:
首先設置第一個元素爲候選主元素,這個毋庸置疑。然後從第二個元素開始往後比較,相同的話計數count++;不相同的話count–;這裏也好懂。**重點 **是當目前的元素與候選主元素不相同的時候,如果count<=0,說明了當前的候選主元素已經個數爲0了,就是說每出現一次這個數(假設是num),都會有另外一個不相等的數進行抵消,num到目前的進度的時候達不到1/2.所以這個時候就必須要更換種子選手了,既然能當上種子選手也說明他在前面的序列中,出現的個數也是相當的多了,不然就會有其他的種子選手替換掉他。所以這時候就換下一個選手作爲種子選手了。
當count<=0時,更換了種子選手,那麼換掉的下一個種子選手可能還沒有換之前的多怎麼辦呢。這個換個角度就能想明白了,既然作爲一名種子選手就是想成爲主元素的,那麼主元素要求就是count>n/2,這就說明,走到最後的時候他能幹掉所有其他的種子選手,是就是每出現一個不一樣的元素,都能找一個元素給抵消掉,不管小夥伴來的有多晚,都能抵消掉。
看兩組樣例:
在這裏插入圖片描述
無論中間的時候種子選手會換給誰當,只要你是主元素,你都能給他們比下去,有這就夠了。

int f12(SqList &L){				//找到出現次數大於length/2的元素 
	int i,num;
	int count=1;
	num=L.data[0];				//設置候選主元素爲第一個 
	for(i=1;i<L.length;i++){	//查找候選主元素 
		if(L.data[i]==num)
			count++;			//與候選主元素相同則計數+1 
		else{
			if(count>0)			//計數count>0說明當前候選主元素不低於1/2 
				count--;
			else{				//count<0則需要更換候選主元素 
				num=L.data[i];
				count=1;
			}
		}
		cout << i << ":" << count << " " << num << endl;
	}
	if(count>0){					
		count=0;
		for(i=0;i<L.length;i++){	//統計實際出現的次數 
			if(L.data[i]==num)
				count++;
		}
	}
	if(count>L.length/2)
		return num;
	else
		return -1;
}
int  f13(SqList &L){			//時間複雜度O(n),空間:O(n)
	int k=0;
	int  a[n+2];
	int  i;
	memset(a,0,sizeof(a));
	for(i=0;i<L.length;i++){	//找到最小的未出現的正整數
		a[L.data[i]]++;
	}
	for(i=1;i<=n+1;i++){
		if(a[i]==0)
			return i;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章