【算法面试题】交换排序问题

算法面试题】交换排序问题
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++;
            }
        }
    }
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值