1、问题描述
有N个瓶子,编号 1 ~ N,放在架子上。
比如有5个瓶子:
2 1 3 5 4
要求每次拿起2个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5
对于这么简单的情况,显然,至少需要交换2次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式为两行:
第一行: 一个正整数N(N<10000), 表示瓶子的数目
第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。
输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。
例如,输入:
5
3 1 2 5 4
程序应该输出:
3
再例如,输入:
5
5 4 3 2 1
程序应该输出:
2
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
2、我对这个问题的看法、理解
在我看来,这个问题考察的是对数组中指定元素的查找,即对对应位置找那个序号对应的瓶子。我们可以把数组的下标看成位置的序号,把数组元素的值看成瓶子的序号。这样就可以问题转化为定数组的下标,然后在所有的数组元素的值中找那个对应的瓶子,找到后交换即可。
**注意:**按顺序查找,只要找到对应的瓶子就交换,交换后开始下个瓶子的查找,排好的瓶子就不再参与下次遍历。
3、关键函数count( )详解
函数功能:实现对瓶子交换次数的统计。
函数执行流程:
——》外层for循环:控制数组元素的移动;
——》if语句判断:判断在那个位置上的瓶子是否与瓶子编号对应;
——》内存for循环:遍历a[i]之后的元素,直至找到那个对的元素;
——》if语句判断:判断是否找到那个对应的元素;
若if语句成立,就交换,把计数因子加1,break语句退出循环;
若if语句不成立,就继续遍历;
——》全部瓶子都排好后,函数结束,返回计数因子;
函数代码:
int count(int n) //统计交换的次数;
{
for(int i=0;i<n;i++) //控制数组元素的移动;
{
if(a[i]!=i+1) //判断在那个位置上的瓶子是否与瓶子编号对应;
{
for(int j=i+1;j<n;j++) //遍历a[i]之后的元素,直至找到那个对的元素;
{
if(a[j]==i+1) //找对应元素;
{
swap(a[i],a[j]); //找到后交换;
number++; //每交换一次,计数因子加1;
break; //结束本次循环,开始下个元素的遍历;
}
}
}
}
return number; //所有的元素判断后,返后总的交换次数number;
}
4、完整解法代码
#include<iostream>
using namespace std;
int a[10000]; //定义数组,存放瓶子的编号;
int number; //统计移动的次数;
void swap(int &a,int &b) //交换数组元素的值,即交换瓶子的编号; 注:定义变量时,要定义成引用型变量,否则数组元素不会互换;
{
int t;
t=a; //通用的交换格式;
a=b;
b=t;
}
int count(int n) //统计交换的次数;
{
for(int i=0;i<n;i++) //控制数组元素的移动;
{
if(a[i]!=i+1) //判断在那个位置上的瓶子是否与瓶子编号对应;
{
for(int j=i+1;j<n;j++) //遍历a[i]之后的元素,直至找到那个对的元素;
{
if(a[j]==i+1) //找对应元素;
{
swap(a[i],a[j]); //找到后交换;
number++; //每交换一次,计数因子加1;
break; //结束本次循环,开始下个元素的遍历;
}
}
}
}
return number; //所有的元素判断后,返后总的交换次数number;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
cout<<count(n);
return 0;
}
5、运行结果
示例1
输入:
5
2 1 3 5 4
应输出:
2
运行结果:
运行环境:DEV c++
示例2
输入:
5
3 1 2 5 4
应输出:
3
运行结果:
运行环境:DEV c++
示例3
输入:
5
5 4 3 2 1
应输出:
2
运行结果:
运行环境:DEV c++
至此,整个题目解答完毕!!!
结语:以上就是我对这个问题的理解、解法,可能存在着更好、更简洁的解法代码,希望大家提出来,我们一起讨论,交换看法,共同进步。若上述代码中存在问题,望大家指正,谢谢大家看到结尾。(∩^∩)
奋斗的2351