Google 2013校招笔试题:用swap排序

5 篇文章 0 订阅
4 篇文章 0 订阅

题目:长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他书的swap,请设计并实现排序。

未排序的元素永远不会指向已排序的元素的位置。比如a[2]=2时,绝对不会存在有a[i]=2, i!=2的情况。

本来想用类似快排的方法,一次排好一个元素,然后分开,但是不知道怎么出错了,代码被我注释了,这里采用简单粗暴的实现方式——一个已连续排序计数器,计数器达到N就是排好序了;碰到没有排序的就交换,然后计数器清零;碰到排好序的就计数器加①。

其实可以每次交换的时候把下标放进一个容器(hash?),然后下次交换可以直接省略比较;

或者每次从未排序的下标中抽取一个swap,然后把swap好的下标从容器中移除。

欢迎指正:

#include <iostream>

using namespace std;

int pos = -1;

// change a[i] with 0
void swap(int *arr, int i){
  if (pos == -1)
    while(arr[++pos]!=0){}
  arr[pos] = arr[pos] ^ arr[i];
  arr[i] = arr[pos] ^ arr[i];
  arr[pos] = arr[pos] ^ arr[i];
  pos = i;
}

// put a[i] at i: if a[a[i]] is not 0, swap once; else swap twice.
int zeroswap(int *arr, int i){ 
    int temp = arr[i];
    if (arr[i]==pos)
      swap(arr, i);
    else {
      swap(arr, arr[i]);
      swap(arr, i);
    }
    return temp;
}

void print(int *arr, int start, int end){
  for(int i = start; i <=end; i++)
    cout << arr[i] << " ";
  cout << endl;
}

// void partition(int *arr, int start, int end){
//   while(start<end && arr[start]==start) start++;
//   while(end>start && arr[end]==end) end--;
//   if(start<end){
//     int ok = zeroswap(arr, start);
//     if(ok>=start&&ok<=end){
//       int left = ok - 1;
//       int right = ok + 1;
//       if(left>=start) 
// 	partition(arr, start, left);  
//       if(right<=end) 
// 	partition(arr, right, end);
//     }
//     else if(ok>end){
//       partition(arr, start, end);
//       partition(arr, end, ok-1);
//     }else{
//       partition(arr, ok+1, start);
//       partition(arr, start, end);
//     }
//   }
//   else if(start==end)
//     if (arr[start]!=start)
//       zeroswap(arr, start);
// }

void sort(int *arr, int size){
  int num = 0;
  int index = 0;
  while(num!=size){
    if(arr[index]==index)
      num++;
    else{
      zeroswap(arr, index);
      num=0;
    }
    if(index==size-1)
      index=0;
    else
      index++;
  }
}

int main(){
  int arr[] = {9, 11, 1, 3, 10, 8, 17, 0, 13, 12, 5, 14, 4, 7, 16, 6, 2, 19, 15, 18};
  sort(arr, 20);
  print(arr, 0, 19);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值