不改变正负数之间相对顺序重新排列数组(时间O(N),空间O(1))

来源:互联网 发布:python 重命名文件 编辑:程序博客网 时间:2024/05/17 06:28
不改变正负数之间相对顺序重新排列数组(时间O(N),空间O(1))

原帖位置:http://blog.csdn.net/v_july_v/article/details/7329314

问题:请看原帖

原帖解决方法评论:
区间翻转的最优解决方法是采用二分法进行区间翻转,因此其最差时间复杂度为O(NlogN),认为该思路无法解决该问题。
例如:
  (+-)(+-)(+-)(+-)(+-)(+-)(+-)(+-)
  (+-)(+-)(+-)(+-)
  (+-)(+-)
  (+-)
  (-+)


新的思路:
(1)桶排序能够在 时间O(N),空间O(1) 实现,那么能否利用桶排序解决该问题,即如何将该问题转换为桶排序问题
(2)通过可逆的修改元素使得数组满足桶排序要求
(3)利用桶排序实现
(4)恢复元素


假设原数组中的全体正数按顺序依次为:a[0],...a[n]

(a[0],a[1],....a[n]) = f(x) => (b[0],b[1],....b[n])= g(x) => (0,1,....,n)  ==> 桶排序
  原始正数(可能相同)               (修改为全不相同正数)            

(0,1,....,n) =g'(x)=> (b[0],b[1],....b[n])=f'(x)=> (a[0],a[1],....a[n])
                            可逆运算恢复数据               可逆运算恢复数据


结论:
由于桶排序能够在 时间O(N),空间O(1) 实现,若可逆函数f(x)、g(x)能够在 时间O(N),空间O(1)中找到并实现,那么就能够解决该问题。




代码:
-- 该代码的实现过程可能产生溢出
-- 是否有更优的方式构造可逆函数f(x)、g(x)


void Order( int *IN_pData,DWORD IN_DataNum ){    DWORD i;    //0:正数个数; 1:负数个数    DWORD Count[2]={0};    int Max=0;    int temp,Position;    ////////////////////////////查找最大绝对值    for( i=0;i<IN_DataNum;i++ )    {        if( ((IN_pData[i]>0) && (IN_pData[i]>Max))          || ((IN_pData[i]<0) && (-IN_pData[i]>Max))     )        {            Max=IN_pData[i];        }    }    Max+=1;    ////////////////////////////查找最大绝对值--End    ////////////////////////////修改值    for( i=0;i<IN_DataNum;i++ )    {        if( IN_pData[i]>=0 )        {            IN_pData[i]+=Max*(Count[0]++);        }        else        {            IN_pData[i]-=(Max*(Count[1]++));        }    }    ////////////////////////////修改值--End    ///////////////////////////////////////////////////此处可优化    //正数起点    Count[0]=Count[1];    //负数起点    Count[1]=0;    ////////////////////////////桶排序    for( i=0;i<IN_DataNum;i++)    {        if( IN_pData[i]>=0 )        {            Position=(IN_pData[i]/Max)+Count[0];            if( Position!=i )            {                temp=IN_pData[Position];                IN_pData[Position]=IN_pData[i];                IN_pData[i]=temp;                i--;            }        }        else        {            Position=(-IN_pData[i]/Max)+Count[1];            if( Position!=i )            {                temp=IN_pData[Position];                IN_pData[Position]=IN_pData[i];                IN_pData[i]=temp;                i--;            }        }    }    ////////////////////////////桶排序--End    ////////////////////////////恢复值    Count[0]=0;    Count[1]=0;    for( i=0;i<IN_DataNum;i++ )    {        if( IN_pData[i]>=0 )        {            IN_pData[i]-=Max*(Count[0]++);        }        else        {            IN_pData[i]+=(Max*(Count[1]++));        }    }    ////////////////////////////恢复值--End    ///////////////////////////////////////////////////此处可优化--End    return ;}



 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 伊织调教 起重机司机学习 ssni 输入梯形上底下底高,输出面积 python语言,输入梯形上底下底高输出面积 网易产品 https://www.csdndoc.com/blog/390696 https://www.cocoacontrols.com 风之教堂 黄色网站 AV网站 439973416 فیلترشکن WS_CLIPCHILDREN设置键在哪里 数据结构(严蔚敏李冬梅)课后答案 ipz809 一个字包含的二进制位数 linux面试 【题目2】设计一个结构体类型,包含姓名、出生日期。其中出生日期又包含年、月、日三部分信息。输入n个好 【题目2】设计一个结构体类型,包含姓名、出生日期。其中出生日期又包含年、月、日三部分信息。输入n个好 结构体比较好友中年纪最小的 matlab三维矩阵可视化 使QQ崩溃 scanIP 按照规定,在高速公路上行使的机动车,达到或超出本车道限速的10%则处200元罚款;若达到或超出50% c语言输入三个数字 c语言如何输入三个数求平均值 c语言如何输入三个数求和 C语言为什么只录入了第一个数字 输入多个数字 c语言scanf只有第一个数字 scanf三个整数 double double类型 www和http 会计 日记账 myamnatfound IntroductiontoIoT IntroductiontoIoT 使用哪种类型的无线网络连接城市中的设备来创建城域网