目录
1,题目描述
Sample Input:
10
3 5 7 2 6 4 9 0 8 1
Sample Output:
9
题目大意
对给出的一系列数字(从0到N-1),不断地将0与其他数字交换,直至数列递增有序。输出至少交换的次数。
2,思路
数据结构
- int index[N]:下标为元素,值为元素所在位置;(eg.index[0]=12,表示0在位置12处)
算法
- 设计for循环,遍历从1到N-1的每一个数,看是否在正确的位置上(index[i] == i);
- 若不在,说明尚未排好序。设计while循环,不断将0与0对应的值进行交换 (swap(index[0],index[index[0]])),每次互换可以确定一个正确位置,直到0回到了位置0(或者是序列有序,0最后才回到正确位置)。如下图第五行所示,此时判断i是否在正确位置(index[i] == i),若不是,则将0与位置i对应元素互换,此次互换不能将一个元素放在正确位置上,但可以保证循环继续进行。
3,AC代码
#include<bits/stdc++.h>
using namespace std;
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
int N, num, cnt = 0;
cin>>N;
int index[N];
for(int i = 0; i < N; i++){
scanf("%d", &num);
index[num] = i;
}
for(int i = 1; i < N; i++){
if(index[i] != i){
while(index[0] != 0){
swap(index[0], index[index[0]]);
cnt++;
}
//跳出循环可能是已经排好序 或是0回到了位置0
if(index[i] != i){ //未排好序
swap(index[0], index[i]); //将i所在的位置换到下标0对应的位置 下一次即可将i跳到正确位置上
cnt++;
}
}
}
cout<<cnt;
return 0;
}
4,解题过程
第一搏
一开始没看清题目(只能元素0与其他元素交换),还一直纳闷,最少不是7步吗?
搜索了其他大神的解法后,才发现,题意没理解对。。。(审题很重要!!!)
第二搏
声明了两个数组,一个data存放原先顺序的数字,另一个index存放每个元素对应的下标(即下标对数字,数字对下标);
不断地将0下标对应的数字,与0交换,并更新index数组;
若0下标对应数字为0,且数组尚未排好序,则随机与一个未确定位置的元素交换(图中红色部分,第一次是0与9交换,第二次是0与1交换,最终的步数都一样)
#include<bits/stdc++.h>
using namespace std;
int N;
int findNext(int index[]){
for(int i = 0; i < N; i++){
if(index[i] != i)
return i;
}
return -1;
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
cin>>N;
int data[N], index[N];//data原始数据 index数据对应的下标
for(int i = 0; i < N; i++){
scanf("%d", &data[i]);
index[data[i]] = i;
}
int pos, p, num = 0;//pos第一个
pos = findNext(index);
while(pos != -1){
if(index[0] == 0){
swap(data[0], data[index[pos]]);
swap(index[0], index[pos]);
num++;
}
while(index[0] != 0){
p = index[0];
swap(data[p], data[index[p]]);
swap(index[0], index[p]);
num++;
}
pos = findNext(index);
}
cout<<num;
return 0;
}
第二搏
欣赏了柳神的做法后(膜!),发现我的做法主要有几点比较耗时:
- 维护了两个数组,一个数组存放原始数列data(下标为应该的顺序,值为当前位置元素,不断更新,直到每个元素都在对应位置),另一个存放元素对应的位置index(下标对应元素,值为元素在data中的位置);【实际上只需要一个index数组即可】
- 使用findNex(逐个遍历数组,看元素是否在其对应位置上)来循环判断算法是否结束;【只需要一个循环从1到N-1即可,若当前元素在正确位置,则跳过,否则不断地将0与其下标对应的元素互换位置。】
单走一个6!