空间复杂度分段分段有序数组合并成有序(空间复杂度为O(1))

查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧!

    标题描述:

    数组A,长度为n,其中A[0, m-1] 和 A[m, n-1],都分别有序。将其合并成有序数组A[0,n-1],要求空间复杂度为O(1)。

    当初的标题条件是数组分段有序,前后两部分已经有序,如果没有空间复杂度的限制,可以通过建立一个长度为n的空间,然后在O(n)时间内归并成一个有序的数组。

    (1)直接插入排序

    常见的比拟排序算法我们都晓得,我们晓得在已经基本排序的基础上,直接插入排序的效率是比拟高的,所以首先我们能想到的就是利用直接插入排序的方法来处理这个问题,时间复杂度T(n) = m*(n-m),这是因为每次肯定插入位置时,最多须要比拟和移动m次,因为前面已经插入的元素已经是在终究位置上了(A[m, n -1]也是有序的原因)。

    详细代码如下:

template <typename Type>
void DirectInsertMerge(Type *array, int low, int high, int m)
{
    if (array == NULL || low >= high || low < 0 || m < low || m > high)
    {
        return;
    }

    Type exchange;
    int j;

    for (int i = m; i <= high; ++i)
    {
        exchange = array[i];

        for (j = i - 1; j >= low; --j)
        {
            if (exchange < array[j])
            {
                array[j + 1] = array[j];
            }
            else
            {
                break;
            }
        }

        if( i == j + 1) break;//插入位置为以后所在位置,整个数组已经有序
 
        array[j + 1] = exchange;
    }
}
    每日一道理
我拽着春姑娘的衣裙,春姑娘把我带到了绿色的世界里。

    (2)另一种解法

    将A[m]与A[0...m-1]的元素顺次顺序比拟,当A[m] < A[i]时,将A[m]<--->A[i]进行交换,然后对A [m...n - 1]进行重新排序使其有序(可采用直接插入),然后顺次重复上述步骤,不过是A[m]与A[i+1...m-1]的元素顺次顺序比拟。因为i前面的元素已经在起该在的位置上了。如下图:

    空间复杂度和分段

    这种算法的时间复杂度和直接插入排序一样,T(n) = m*(n-m),源代码如下:

template <typename Type>
void MergePartialSeq(Type *array, int low, int high, int m)
{
    if (array == NULL || low >= high || low < 0 || m < low || m > high)
    {
        return;
    }

    Type exchange;

    int i = low;
    while( i < m)
    {
        while (i < m && array[m] >= array[i])
            ++i;

        if(i == m) 
            break;

        exchange = array[i];
        array[i] = array[m];
        array[m] = exchange;

        int j = m + 1;
        exchange = array[m];

        while(j <= high && array[j] < exchange)
        {
            array[j - 1] = array[j];
            ++j;
        }

        array[j - 1] = exchange;

        ++i;
    }
}

    May 28, 2013 @lab

文章结束给大家分享下程序员的一些笑话语录: 话剧:程序员过沟
  本剧内容纯属虚构,如有雷同……HEHE……俺也没办法了。
  话说某市街道改建,某某软件公司门口横七竖八挖了几条大沟。一群程序员(SDK程序员赵某,VB程序员钱某,VC程序员孙某,DELPHI程序员李某)下班从公司里出来,看到门前的几条沟,于是各显神通……门前第一条沟也就半米来宽,SDK程序员赵某二话没说,轻轻一跃跳了过去,看到其它人纷纷把随身携带的公文包(类库)横在沟上踩着过沟,不屑地说,这么小一条沟,犯得着小题大做用那个吗?看我多么轻松多么洒脱多么……多么……(众人皆怒目横视之……)
  接着第二条沟有点宽度。SDK程序员赵某还是还是一马当先,飞跃而起……不好,还差一点才到……幸好凭着多年的(跳远?编程?)经验,单手抓住沟沿,颤巍巍地爬了上来,嘴里还念念有词“高手就是高手啊,虽然差一点就……不过毕竟……HEHE……跳远是过沟的基础嘛,有基础(SDK)就有一切的说……”(众人作瞠目结舌状……)看到别人跳过去了,可自己又跳不了那么远,只好再想办法了……VB程序员钱某,DELPHI程序员李某打开手提,连上手机,开始上网找可供过沟的控件……VC程序员孙某却不慌不忙,打开公文包,把几块衬板拆了下来,然后三下五除二拼成一个简易木桥……“虽然这几个板子(类)做得不怎么样,不过先把这个项目应付过去,有时间我自己做一个好了……”于是踩着板子过了沟。
  这时钱某和李某也分别找到了合适的东东。钱某找到的是“钢丝绳.ocx”,安装简单,使用方便,拉出一头,对孙某说“大虾,顺手拉兄弟一把……”,于是把绳子系在沟两边的绿化树木上,踩着钢丝就过了沟。刚刚站稳就四方作揖,“小生这里有礼了”。这时一戴着黄袖圈的老太太跳了出来,抓住钱某,“破坏绿化树木,罚款XXXX元,交钱,交钱,交钱!”(老人家作双枪老太婆怒视伪军状
……钱某被逼无奈,只好边掏钱,边对着后台叫道“导演,我这可是因公牺牲,不给个烈士称号也得报销”,后台一个臭鸡蛋飞出,“叫什么叫,我这个月的粮饷还不知哪里去领呢,都什么时代了,你不下岗都不错了……”)
  李某看着刚刚好不容易从台湾拖回来的“铝条.ZIP”

--------------------------------- 原创文章 By
空间复杂度和分段
---------------------------------

posted @ 2013-05-28 23:56  坚固66  阅读(943)  评论(0编辑  收藏  举报