现有1,2……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且只能交换两个数

来源:互联网 发布:事情进度跟踪软件 编辑:程序博客网 时间:2024/05/10 20:52


这是今天遇到的一个笔试题,当时想到的思路就是把数值和数组下标关联起来,后来事实证明这个思路是正确的,但是我写的代码出现了一些小偏差,代码如下

//错误代码:#include <iostream>using namespace std;int main(){ int arr[5] = {4, 2, 5, 3, 1}; for(int i = 0; i < 5;i++) {  int pos = arr[i];  int temp = arr[pos - 1];  arr[pos - 1] = pos;  arr[i] = temp; } for(int i = 0; i < 5; i++) {  cout << arr[i] << endl; } cin.get(); return 0;}


后经测试这种算法不能得到正确的结果,于是百度之……

(这也是一个非常不好的习惯吧,没有经过自己的调试和思考,直接引用别人的思路……)

看完别人的代码之后,我知道了我的问题出现在哪里,例如我上面的数组,第一个元素是4,则arr[3] = 4,arr[0]则改为3,而后i自增了1开始交换下一个元素,这样并不符合arr[0]应该存储的值为1,当遍历完整个数组的时候,如果之前交换到前面的数字并不匹配应该存储的下标位置上,则不再处理,于是结果错误


看完别人的代码后也明白了别人解决这个问题的方法:

即当交换过来的数值不能匹配这个位置时,下标不向前走,继续进行交换,直到交换过来的数字匹配此位置时,下标向前进

具体代码:


#include <iostream>using namespace std;int main(){ int arr[5] = {4, 2, 5, 3, 1}; for(int i = 0; i < 5;) {  int pos = arr[i];  int temp = arr[pos - 1];  arr[pos - 1] = pos;  arr[i] = temp;  if(arr[i] == i + 1)  {   i++;  } } for(int i = 0; i < 5; i++) {  cout << arr[i] << endl; } cin.get(); return 0;}


这样就能够得到正确的结果

后经过自己在纸上的推演,发现此种算法即使在数值和位置匹配的情况下也会将数值复制到临时变量中再复制回来,平白增加了开销,应该能够进行优化,即在复制之前先行判断数值与位置是否匹配

#include <iostream>using namespace std;int main(){ int arr[10] = {4, 2, 5, 3, 1}; int i = 0; while(i < 5) {  if(arr[i] == (i + 1))   i++;  else  {   int pos = arr[i];   int temp = arr[pos - 1];   arr[pos - 1] = pos;   arr[i] = temp;  } } for(int i = 0; i < 5; i++) {  cout << arr[i] << endl; } cin.get(); return 0;}

这样当数值与位置匹配时就会跳过此位置进入下一位置,从而减少了开销


反思,这是我在看了别人的代码之后才知道自己错在哪里,应该怎么解决,我想我缺乏的正是这种解决问题的能力,如果不参考别人的代码,能否想到这样来解决?如果题目不给提示,我能否想到使用交换的方式来做?路还很长……


0 0
原创粉丝点击