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

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

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

[cpp]  view plain copy
  1. //错误代码:  
  2.   
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. int main()  
  7. {  
  8.  int arr[5] = {4, 2, 5, 3, 1};  
  9.  for(int i = 0; i < 5;i++)  
  10.  {  
  11.   int pos = arr[i];  
  12.   int temp = arr[pos - 1];  
  13.   arr[pos - 1] = pos;  
  14.   arr[i] = temp;  
  15.  }  
  16.   
  17.  for(int i = 0; i < 5; i++)  
  18.  {  
  19.   cout << arr[i] << endl;  
  20.  }  
  21.   
  22.  cin.get();  
  23.  return 0;  
  24. }  

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

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

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


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

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

具体代码:

[cpp]  view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. int main()  
  5. {  
  6.  int arr[5] = {4, 2, 5, 3, 1};  
  7.  for(int i = 0; i < 5;)  
  8.  {  
  9.   int pos = arr[i];  
  10.   int temp = arr[pos - 1];  
  11.   arr[pos - 1] = pos;  
  12.   arr[i] = temp;  
  13.   if(arr[i] == i + 1)  
  14.   {  
  15.    i++;  
  16.   }  
  17.  }  
  18.   
  19.  for(int i = 0; i < 5; i++)  
  20.  {  
  21.   cout << arr[i] << endl;  
  22.  }  
  23.   
  24.  cin.get();  
  25.  return 0;  
  26. }  

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

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

[cpp]  view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. int main()  
  5. {  
  6.  int arr[10] = {4, 2, 5, 3, 1};  
  7.   
  8.   
  9.  int i = 0;  
  10.  while(i < 5)  
  11.  {  
  12.   if(arr[i] == (i + 1))  
  13.    i++;  
  14.   else  
  15.   {  
  16.    int pos = arr[i];  
  17.    int temp = arr[pos - 1];  
  18.    arr[pos - 1] = pos;  
  19.    arr[i] = temp;  
  20.   }  
  21.  }  
  22.   
  23.  for(int i = 0; i < 5; i++)  
  24.  {  
  25.   cout << arr[i] << endl;  
  26.  }  
  27.   
  28.  cin.get();  
  29.  return 0;  
  30. }  

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

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

【本文转至】http://blog.csdn.net/a3789910/article/details/41384567


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值