對一個數組按照給定的下標進行排序,僅僅使用兩兩交換的方式,要求不能對數組進行擴容,儘可能少的額外空間。
如:原數組爲A,B,C,D,E,現在給定的新位置爲3,0,1,4,2,那麼排序後爲D,A,B,E,C,
void SwapSort(int *pArr,int *pPos,int n)
1.解決問題
這是最近看到的一道面試題,感覺突然一下不容易想到,所以特此來寫一下:
實現代碼:
void SwapSort(int *pArr, int *pPos, int n)
{
assert(pArr);
assert(pPos);
int tmp = pArr[0];
int i = 0;
for (int j = 0; j < n; )
{
if (pPos[i] != i)
{
tmp = pArr[i];
int prevpos = i;
while (1)
{
pArr[i] = pArr[pPos[i]];
i = pPos[i];
j++;
if (prevpos == pPos[i])
{
pArr[i] = tmp;
j++;
break;
}
}
}
else
{
i++;
j++;
}
}
}
2.發散考慮
當我寫完這種方式的時候,我進行了其他案例的測試
比如我給出了pPos[]={2,0,1,3,4},或者是pPos[]={3,4,1,0,2}。
最後在這裏我總結出一個特點,就是這個時候如果我們按照上述那樣操作的話,最終會出現一種問題,只能調整一個範圍內的數據成正常順序,另外一個不相關的範圍的順序就會出問題了。
首先我想到的是採用一個數組記錄所有的狀態,每把一個放到正常位置以後就把輔助數組當中的狀態改爲1,否則就爲0,但是,這樣,空間複雜度就變爲了O(N),所以我們想到下一種辦法
void swapsort(int *parr, int *ppos, int n)
{
assert(parr);
assert(ppos);
int tmp = parr[0];
int i = 0;
for (int j = 0; j < n;)
{
while (i == ppos[i])
{
i++;
j++;
}
//當全部填充後,可以考慮跳出
if (i >= n)
break;
if (ppos[i] != i)
{
tmp = parr[i];
int prevpos = i;
while (1)
{
parr[i] = parr[ppos[i]];
int newpos = ppos[i];
ppos[i] = i;
i = newpos;
j++;
if (prevpos == ppos[i])
{
parr[i] = tmp;
ppos[i] = i;
i = prevpos + 1;
j++;
break;
}
}
}
}
}
3.總結
對於面試題中好多東西我們是都可能沒見過的,但是在這個其中,大部分都是我們見過的一些的變形,所以需要熟練的使用我們所學習的數據結構和算法,當然,前提是對這些結構和算法的概念一定要清楚的記得。