【算法面試題】交換排序問題

算法面試題】交換排序問題
2016年12月19日 17:32:25 _stark 閱讀數:298更多
所屬專欄: 刷題
版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/bit_clearoff/article/details/53744749
面試題

原數組pArr爲[‘A’,’B’,’C’,’D’,’E’],現在給定新位置pPos[3,0,1,4,2],要求只能採用交換的方式並按照新位置進行排序,要求空間複雜度爲O(1)。排好序後的序列爲
D A B E C.
問題分析

如果不給限制條件這道題還是非常簡單的,現在給定了空間複雜度的限制爲O(1),也就是說我們不能再原有數組的基礎上再來開闢新的空間,這道問題就變得有些複雜了。
在這裏插入圖片描述代碼如下:

void SwapSort(vector<char>& pArr,vector<int>& pPos)
{
    assert(pArr.size()>0);
    assert(pPos.size()>0);
    assert(pArr.size() == pPos.size());

    char tmp = pArr[0];
    size_t counts = 1;
    int index = 0;
    while (counts < pArr.size())        //循環終止條件
    {
        if (index != pPos[index])
        {
            pArr[index] = pArr[pPos[index]];
            index = pPos[index];
            counts++;
        }
        else
        {
            index++;
            counts++;
        }
    }
    //最後一次填坑需要進行測試
    if (index != pPos[index])
    {
        pArr[index] = tmp;
    }
}

但是這種解法其實是有缺陷的,當我們給出的新位置的元素如果兩次如果是之前已經交換過的元素的下標,那麼排序就會出現問題,如我們給出pPos=[3 1 0 2 4]結果就會出現問題,因爲當我們排道pArr=[D B A C E]時,坑已經在正確的位置上了,所以纔會導致我們後面填坑時又重新出現了A導致排序序列不正確。

改進算法

爲了防止pArr中已經“坑”已經被放在正確位置又在後面重復填充,所以每次我們將坑填完後需要重新挖坑,新挖的坑爲填坑後的下標出的第一個index!=pPos[index]的下標,同時每次交換元素時我們要把當前下標更新爲pPos裏的下標。

代碼如下:

void NewSwapSort(vector<char>&pArr, vector<int>& pPos)
{
    assert(pArr.size()>0);
    assert(pPos.size()>0);
    assert(pArr.size() == pPos.size());

    char tmp    = pArr[0];                       //挖坑
    int  tmpPos = 0;                             //拿到所挖的坑位置的下標
    size_t counts = 1;
    int index = 0;

    while (counts < pArr.size())
    {
        while (index == pPos[index])
        {
            index++;
            counts++;
        }

        /*if (index == pArr.size())
            break;*/

        //在index處挖坑
        tmp = pArr[index];
        tmpPos = index;

        while (1)
        {
            //完成交換的條件
            if (index == pArr.size())
                break;
            if (index != pPos[index])
            {
                if (tmpPos == pPos[index])
                {
                    //如果當前pPos中的下標與當前坑的下標相同
                    //把坑的元素填入pArr中
                    pArr[index] = tmp;
                    pPos[index] = index;

                    index++;
                    break;
                }
                //如果當前pPos中的下標與當前坑的下標不同
                //則交換pArr中pPos[index]中的元素給當前位置
                pArr[index] = pArr[pPos[index]];

                //更新pPos中的對應下標和當前下標
                int j = pPos[index];
                pPos[index] = index;
                index = j;
                counts++;
            }
            else
            {
                index++;
                counts++;
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章