版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/buynow123/article/details/44852047
之前也写了不少代码,感觉是无聊的小说,乏陈无味。前些时候听妹妹说研究生申请到卡内基-梅隆大学读计算机专业,由衷羡慕。偶然间在书店看到了一本书Programming Pearls,看作者是卡内基-梅隆大学教授,买下慢慢品读。“小才女”曾经告知我,读书不是快速看一遍,需要引发思考,一本好书更要慢慢的思考。
下面是群里面发的一道题,
初看题时,一道排序题,会想到直接插入排序,归并排序,快速排序云云,这也许是思维定式,大部分同学都会这样思考,我也是。由于此题目的特殊性,第一印象的算法,时间复杂度大概都在N3方级,只记得算法老师说过,3次方级基本上是不能接受的级别。突然想到Programming Pearls开篇就提到了一种排序算法,静下心来重新分析一下此题目。
输入:一个乱序序列(n个正整数),序列是连续的,整数中间绝对不会有重复。
输出:排序,遍历到小整数时,前面遍历过连续的大整数要一并输出。
以上分析,符合Jon在书开篇中提到的问题,可以用位图或位向量来表示集合。可以用10位长的字符串来表示一个所有元素都小于10的简单的非负整数集合【1,2,3,5,8】:0 1 1 1 0 1 0 0 1 0
所以我写了如下代码,可以满足上述题目要求,最坏情况下的时间复杂度为N2,基本可以接受。额外空间使用方面,使用的char数组记录,空间为初始数组的1/4,如果使用真正的bit来表示数据的存在,空间可以缩小为现在的1/8。
希望大家能够提供更加优化的算法,共同学习。
#include "stdafx.h"
#include "iostream"
using namespace std;
//Time complexity ,worst=n*n
void miracleSort(int *arr, int size, int first)
{
char *pBit = NULL; //alloc bit array to mark
int i = 0,j = 0;
int offset = first; // offset variable,start at 0
if(size < 1)
{
cout<<"error input"<<endl;
return;
}
pBit = new char[size];
memset(pBit,0,sizeof(char)*(size));// initial all bit to 0
for(i; i<size; i++) //main loop,sort by bit
{
pBit[arr[i]-offset] = 1; //mark 1 means that find it
if( pBit[first-offset] == 1)// find output number
{
cout<<first<<" ";
for(j=first+1-offset; j<size; j++)//if have series ,output
{
if(pBit[j] == 0)
{
first = j+offset; //reset variable
break;
}
else
{
cout<<j+offset<<" " ;
}
}
cout<<endl;
}
}
delete []pBit;
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
int arr1[10] = {1, 2, 5, 8, 10, 4, 3, 6, 9, 7};
int arr2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int arr3[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
int arr4[10] = {1, 2, 5, 8, 6, 4, 3, 7, 9, 10};
int arr5[10] = {5, 6, 3, 4, 8, 7, 9, 10};
miracleSort(arr1, 10, 1);
cout<<endl;
miracleSort(arr2, 10, 1);
cout<<endl;
miracleSort(arr3, 10, 1);
cout<<endl;
miracleSort(arr4, 10, 1);
cout<<endl;
miracleSort(arr5, 8, 3);
return 0;
}