思路沒問題,但細節上還欠缺,運行時兩個測試點運行超時,定位在兩個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;
}