A1067

思路沒問題,但細節上還欠缺,運行時兩個測試點運行超時,定位在兩個for循環上,卻不知怎麼優化.

#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=100010;
int m[maxn];
int a[maxn],n;
bool judgeSort(){
	for(int i=1;i<n;i++){
		if(a[i]!=i)return false;
	}
	return true;
}
int main(){
	#ifdef ONLINE_JUDGE
	#else
		freopen("1.txt","r",stdin);
	#endif
	int total=0;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		m[a[i]]=i;
	}
	while(1){
		if(m[0]==0){                                 //若此時0所在數組下標恰好爲0,則要判斷數組是否已經有序 
			if(judgeSort()){                         //若已有序,則退出循環 
				break;
			}else{
				for(int i=1;i<n;i++){                //找到第一個沒在自己該在的序號上的數,與0交換 
					if(a[i]!=i){
						m[a[i]]=0;                   //更新該數所在的數組下標 
						m[0]=i;                      //更新0所在的數組下標 
						a[0]=a[i];
						a[i]=0;
						break;
					}
				}
			}
		}else{
			int temp=m[0];
			m[0]=m[temp];
			a[m[temp]]=0;                             //這步省不得,因爲最後要通過排序判斷是否可退出循環 
			m[temp]=temp;
			a[temp]=temp;
		}
		total++;
	}
	printf("%d",total);
	return 0;
}

看了算法筆記才茅塞頓開,我的寫法每次都要從1開始遍歷尋找第一個不在本位上的數,更傻的是我還寫了兩遍,judgeSort中寫過還在之後的for循環中又寫了一遍,明明可以直接將judgeSort中獲取到的保存下來使用.況且尋找也不用每次從頭開始尋找,因爲之前找到的數k都已經與0交換過了,可以將k及之前的數過掉,直接從k開始向後遍歷,這樣等到全部結束,k一共只遍歷了n遍,而我之前的寫法每次最多遍歷n遍,遇到極端情況就會導致超時.

#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=100010;
int m[maxn];
int a[maxn],n,t=1;							//在遍歷沒在自己本位上的數時,更新好遍歷的起始位置,減少遍歷次數 
bool judgeSort(){
	for(int i=t;i<n;i++){
		if(a[i]!=i){						//找到第一個沒在自己本位上的數
			t=i;
			return false;
		}
	}
	return true;
}
int main(){
	#ifdef ONLINE_JUDGE
	#else
		freopen("1.txt","r",stdin);
	#endif
	int total=0;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		m[a[i]]=i;
	}
	while(1){
		if(m[0]==0){                                 //若此時0所在數組下標恰好爲0,則要判斷數組是否已經有序 
			if(judgeSort()){                         //若已有序,則退出循環 
				break;
			}
			m[a[t]]=0;                   			//更新該數所在的數組下標 
			m[0]=t;                      			//更新0所在的數組下標 
			a[0]=a[t];
			a[t]=0;
		}else{
			int temp=m[0];
			m[0]=m[temp];
			a[m[temp]]=0;                             //這步省不得,因爲最後要通過排序判斷是否可退出循環 
			m[temp]=temp;
			a[temp]=temp;
		}
		total++;
	}
	printf("%d",total);
	return 0;
}

算法筆記中的思路值得借鑑!(詳見p161)
每讀入一個數,將其作爲數組下標,將其出現位置作爲數組中存放的數.

#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=100010;
int main(){
	#ifdef ONLINE_JUDGE
	#else
		freopen("1.txt","r",stdin);
	#endif
	int a[maxn],n,left,k=1,total=0;
	scanf("%d",&n);
	left=n-1;
	for(int i=0;i<n;i++){
		int temp;
		scanf("%d",&temp);
		a[temp]=i;
		if(temp==i&&temp!=0)left--;              //此處漏寫了temp!=0,若0在本位,不應該left--,因爲之後0還會不斷變動 
	}
	while(left>0){
		if(a[0]==0){
			while(k<n){
				if(a[k]!=k){
					swap(a[0],a[k]);
					break;
				}
				k++;
			}
		}else{
			swap(a[0],a[a[0]]);
			left--;
		}
		total++;
	}
	printf("%d",total);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章