现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
现在求算法将整个数组排序,要求时间复杂度O(n),空间复杂度O(1)。 如果有解,请给出程序;如果无解,请证明。
================================================================
为了简化描述,避免处理细节,在此给出输入条件:
1 输入:一个int型数组、长度n 和前半部分长度m(不用自己扫描)。
2 数组已经排序的两部分都是递增的,且长度都不为0;排序后要求整个数组递增。
26 个解决方案
#1
时间复杂度为O(N)应该没问题吧,从一个数组里取一个元素出来与另一个若干元素来比较实现排序,看似复杂,其时间复杂度并未超出N的一次多项式.空间复杂度为O(1)的话,不明白什么意思.不过如果怕一个变量产生多个拷贝的话,用指针数组或许可以解决这个问题.
#2
应该是不行的.否则stl中的inplace_merge算法就用这个了.
#3
现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
#4
补充一下,如果问题是:
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
除非是特殊情况,否则不存在此通用算法。
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
除非是特殊情况,否则不存在此通用算法。
#5
mark 一下
#6
up 一下
#7
#define n 10
#define m 4
char str[n] = {...};
char *p = &str[0];
char *q = &str[m];
char t;
int i;
t = *p;
for(i = 0; i < n; i++)
{
if(*p < *q)
{
t = *q;
p++;
}
else
{
t = *p;
*p = *q;
*q = t;
q++;
}
}
#define m 4
char str[n] = {...};
char *p = &str[0];
char *q = &str[m];
char t;
int i;
t = *p;
for(i = 0; i < n; i++)
{
if(*p < *q)
{
t = *q;
p++;
}
else
{
t = *p;
*p = *q;
*q = t;
q++;
}
}
#8
回复人: ZhangYv(我被降级了,哭>_<) ( ) 信誉:100 2006-01-18 18:57:00 得分: 0
现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
===========
你想的太简单了,你怎么知道这两个数组里的数据都是严格递增的?
不过后来的补充倒还是不错
我想这个问题时间复杂度应该在N的一次幂的数量级内,空间复杂度只要交换指针位置就行,不必产生中间变量之类的额外消耗
其实这个问题可以改造成两个有序数列的合并问题,普通的算法就可以实现O(n)
现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
===========
你想的太简单了,你怎么知道这两个数组里的数据都是严格递增的?
不过后来的补充倒还是不错
我想这个问题时间复杂度应该在N的一次幂的数量级内,空间复杂度只要交换指针位置就行,不必产生中间变量之类的额外消耗
其实这个问题可以改造成两个有序数列的合并问题,普通的算法就可以实现O(n)
#9
这就是并归排序,按数据结构书中说的最好时间是O(nlgn)辅助空间是O(n)
看来是实现不了你的期望了,但如果哪位能做到就太伟大了:)
看来是实现不了你的期望了,但如果哪位能做到就太伟大了:)
#10
看了stl中的inplace_merge
它倒是在内存充足的情况下能实现线形时间,但怎样实现的呢?
哪位高手能给出时间O(n)空间不限的算法
它倒是在内存充足的情况下能实现线形时间,但怎样实现的呢?
哪位高手能给出时间O(n)空间不限的算法
#11
有意思。up
#12
两个有序表的一次归并排序算法
本来就是0(N)吧!
空间也是0(1)啊
//------------------------------------------------
这里其实就是两个顺序表!
因为第二个表的头一个元素位置已知
本来就是0(N)吧!
空间也是0(1)啊
//------------------------------------------------
这里其实就是两个顺序表!
因为第二个表的头一个元素位置已知
#13
用归并排序的思路
int a[N];//整个数组
int S1=0,S2=M;
int E1=0,E2=N;//两个有序表的首尾
int i=S1,j=S2;
int t;
while(i<S1 && j<S2)
{
if(a[i]>a[j])
{
swap(a[i],a[j]);//大的放后面,此处就需要O(1)的空间
i++;
break;
}
if(a[i]<a[j])
{
j++;
break;
}
i++;
swap(a[i],a[j]);
}
这样循环次数最多就n次。时间O(n)。
空间仅需要一个用于交换的,O(1)
int a[N];//整个数组
int S1=0,S2=M;
int E1=0,E2=N;//两个有序表的首尾
int i=S1,j=S2;
int t;
while(i<S1 && j<S2)
{
if(a[i]>a[j])
{
swap(a[i],a[j]);//大的放后面,此处就需要O(1)的空间
i++;
break;
}
if(a[i]<a[j])
{
j++;
break;
}
i++;
swap(a[i],a[j]);
}
这样循环次数最多就n次。时间O(n)。
空间仅需要一个用于交换的,O(1)
#14
这样循环次数最多就n次。时间O(n)。
空间仅需要一个用于交换的,O(1)
-----------------------------------------------
肯定不行,不信你试试
空间仅需要一个用于交换的,O(1)
-----------------------------------------------
肯定不行,不信你试试
#15
这道题基本不可能找到楼主所说的那种复杂度的算法。前面几位提到的归并排序要么需要O(N)的数组来记录二分归并后的结果,要么需要O(N)的空间来模拟一个类似链表的操作。就我目前所看过的所有数据结构书上的算法,我看他们还不太可能已经解决了楼主的问题,肯定需要额外的存储空间的。
#16
这个不是华为的面试题么?
我看的答案:
void testpaixu()
{ int a[10]={3,6,8,4,2,9,7,1,5,10};
int b,i;
for(i=0;i<10;i++)
{
b=a[a[i]-1];
a[a[i]-1]=a[i];
a[i]=b;
}
for(i=0;i<10;i++)
printf("%d ",a[i]);
}
我看的答案:
void testpaixu()
{ int a[10]={3,6,8,4,2,9,7,1,5,10};
int b,i;
for(i=0;i<10;i++)
{
b=a[a[i]-1];
a[a[i]-1]=a[i];
a[i]=b;
}
for(i=0;i<10;i++)
printf("%d ",a[i]);
}
#17
以前看到的答案,贴出来给大家一起分享。
#18
oosky2004(oosky) 的只适合严格递增,内容只能是(1--n)的
#19
oosky2004(oosky) 的不行。
因为oosky2004的题目中元素是1~10
这暗示可以从元素的值直接知道其位置。
恩,看来很可能是无解的了,不晓得有人可以证明么?
因为oosky2004的题目中元素是1~10
这暗示可以从元素的值直接知道其位置。
恩,看来很可能是无解的了,不晓得有人可以证明么?
#20
证明已经有了:
结果是否定,方法是反证法,即没人能证明有解开的方法,就能说明没有方法:)
结果是否定,方法是反证法,即没人能证明有解开的方法,就能说明没有方法:)
#21
//n,m
//没那么复杂吧?不就是二路归并算法么?
int nList[n], ans[n];
int i,j,k;
for(i=0,j=m,k=0; i<m&&j<n; k++)
{
if(nList[i]>nList[j])
{
ans[k] = nList[i];
i++;
}
else
{
ans[k] = nList[j];
j++;
}
}
if(i<m)
{
for(;i<m; i++,k++)
{
ans[k] = nList[i];
}
}
else
{
for(;j<n; j++,k++)
{
ans[k] = nList[j];
}
}
//ans为排序后结果
/如果算上ans空间, 那应该是O(n),o(n)
http://www.ohyee.net
//没那么复杂吧?不就是二路归并算法么?
int nList[n], ans[n];
int i,j,k;
for(i=0,j=m,k=0; i<m&&j<n; k++)
{
if(nList[i]>nList[j])
{
ans[k] = nList[i];
i++;
}
else
{
ans[k] = nList[j];
j++;
}
}
if(i<m)
{
for(;i<m; i++,k++)
{
ans[k] = nList[i];
}
}
else
{
for(;j<n; j++,k++)
{
ans[k] = nList[j];
}
}
//ans为排序后结果
/如果算上ans空间, 那应该是O(n),o(n)
http://www.ohyee.net
#22
O(n),o(n)?
你每看清题目还是没戴眼睛?
你每看清题目还是没戴眼睛?
#23
100分买一个2路归并的算法
#24
补充一下,如果问题是:
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
===============================
如果 m = k = 1,那么……
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
===============================
如果 m = k = 1,那么……
#25
to lzf_china(岁月如歌)
是在同一个数组原地排序,不是二路归并。
嗯,看来不得不承认 0000000009(韩雷)的诡辩了。。。
明天就结帖
是在同一个数组原地排序,不是二路归并。
嗯,看来不得不承认 0000000009(韩雷)的诡辩了。。。
明天就结帖
#26
题目不清,有点像华为的作风。基本上猜题就让你累个半死,然后还以此来鄙视你的专业水平不行。嘿嘿。这种题目有N种可能性,既可能有解,也可能没解。他要说简单,就是二路归并嘛,找个数空余数组,两个指针,完事。他要说不简单,就非说这个题没解。怎么说都是对的,你拿他没撤。呵呵
#1
时间复杂度为O(N)应该没问题吧,从一个数组里取一个元素出来与另一个若干元素来比较实现排序,看似复杂,其时间复杂度并未超出N的一次多项式.空间复杂度为O(1)的话,不明白什么意思.不过如果怕一个变量产生多个拷贝的话,用指针数组或许可以解决这个问题.
#2
应该是不行的.否则stl中的inplace_merge算法就用这个了.
#3
现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
#4
补充一下,如果问题是:
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
除非是特殊情况,否则不存在此通用算法。
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
除非是特殊情况,否则不存在此通用算法。
#5
mark 一下
#6
up 一下
#7
#define n 10
#define m 4
char str[n] = {...};
char *p = &str[0];
char *q = &str[m];
char t;
int i;
t = *p;
for(i = 0; i < n; i++)
{
if(*p < *q)
{
t = *q;
p++;
}
else
{
t = *p;
*p = *q;
*q = t;
q++;
}
}
#define m 4
char str[n] = {...};
char *p = &str[0];
char *q = &str[m];
char t;
int i;
t = *p;
for(i = 0; i < n; i++)
{
if(*p < *q)
{
t = *q;
p++;
}
else
{
t = *p;
*p = *q;
*q = t;
q++;
}
}
#8
回复人: ZhangYv(我被降级了,哭>_<) ( ) 信誉:100 2006-01-18 18:57:00 得分: 0
现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
===========
你想的太简单了,你怎么知道这两个数组里的数据都是严格递增的?
不过后来的补充倒还是不错
我想这个问题时间复杂度应该在N的一次幂的数量级内,空间复杂度只要交换指针位置就行,不必产生中间变量之类的额外消耗
其实这个问题可以改造成两个有序数列的合并问题,普通的算法就可以实现O(n)
现有一个数组,长度为n,其前m个元素和后n-m个元素都已经排序过了。
----------------------------------
说明这个数组本来就是排序过了,其实你什么都不需要做,属于有病的题目。
===========
你想的太简单了,你怎么知道这两个数组里的数据都是严格递增的?
不过后来的补充倒还是不错
我想这个问题时间复杂度应该在N的一次幂的数量级内,空间复杂度只要交换指针位置就行,不必产生中间变量之类的额外消耗
其实这个问题可以改造成两个有序数列的合并问题,普通的算法就可以实现O(n)
#9
这就是并归排序,按数据结构书中说的最好时间是O(nlgn)辅助空间是O(n)
看来是实现不了你的期望了,但如果哪位能做到就太伟大了:)
看来是实现不了你的期望了,但如果哪位能做到就太伟大了:)
#10
看了stl中的inplace_merge
它倒是在内存充足的情况下能实现线形时间,但怎样实现的呢?
哪位高手能给出时间O(n)空间不限的算法
它倒是在内存充足的情况下能实现线形时间,但怎样实现的呢?
哪位高手能给出时间O(n)空间不限的算法
#11
有意思。up
#12
两个有序表的一次归并排序算法
本来就是0(N)吧!
空间也是0(1)啊
//------------------------------------------------
这里其实就是两个顺序表!
因为第二个表的头一个元素位置已知
本来就是0(N)吧!
空间也是0(1)啊
//------------------------------------------------
这里其实就是两个顺序表!
因为第二个表的头一个元素位置已知
#13
用归并排序的思路
int a[N];//整个数组
int S1=0,S2=M;
int E1=0,E2=N;//两个有序表的首尾
int i=S1,j=S2;
int t;
while(i<S1 && j<S2)
{
if(a[i]>a[j])
{
swap(a[i],a[j]);//大的放后面,此处就需要O(1)的空间
i++;
break;
}
if(a[i]<a[j])
{
j++;
break;
}
i++;
swap(a[i],a[j]);
}
这样循环次数最多就n次。时间O(n)。
空间仅需要一个用于交换的,O(1)
int a[N];//整个数组
int S1=0,S2=M;
int E1=0,E2=N;//两个有序表的首尾
int i=S1,j=S2;
int t;
while(i<S1 && j<S2)
{
if(a[i]>a[j])
{
swap(a[i],a[j]);//大的放后面,此处就需要O(1)的空间
i++;
break;
}
if(a[i]<a[j])
{
j++;
break;
}
i++;
swap(a[i],a[j]);
}
这样循环次数最多就n次。时间O(n)。
空间仅需要一个用于交换的,O(1)
#14
这样循环次数最多就n次。时间O(n)。
空间仅需要一个用于交换的,O(1)
-----------------------------------------------
肯定不行,不信你试试
空间仅需要一个用于交换的,O(1)
-----------------------------------------------
肯定不行,不信你试试
#15
这道题基本不可能找到楼主所说的那种复杂度的算法。前面几位提到的归并排序要么需要O(N)的数组来记录二分归并后的结果,要么需要O(N)的空间来模拟一个类似链表的操作。就我目前所看过的所有数据结构书上的算法,我看他们还不太可能已经解决了楼主的问题,肯定需要额外的存储空间的。
#16
这个不是华为的面试题么?
我看的答案:
void testpaixu()
{ int a[10]={3,6,8,4,2,9,7,1,5,10};
int b,i;
for(i=0;i<10;i++)
{
b=a[a[i]-1];
a[a[i]-1]=a[i];
a[i]=b;
}
for(i=0;i<10;i++)
printf("%d ",a[i]);
}
我看的答案:
void testpaixu()
{ int a[10]={3,6,8,4,2,9,7,1,5,10};
int b,i;
for(i=0;i<10;i++)
{
b=a[a[i]-1];
a[a[i]-1]=a[i];
a[i]=b;
}
for(i=0;i<10;i++)
printf("%d ",a[i]);
}
#17
以前看到的答案,贴出来给大家一起分享。
#18
oosky2004(oosky) 的只适合严格递增,内容只能是(1--n)的
#19
oosky2004(oosky) 的不行。
因为oosky2004的题目中元素是1~10
这暗示可以从元素的值直接知道其位置。
恩,看来很可能是无解的了,不晓得有人可以证明么?
因为oosky2004的题目中元素是1~10
这暗示可以从元素的值直接知道其位置。
恩,看来很可能是无解的了,不晓得有人可以证明么?
#20
证明已经有了:
结果是否定,方法是反证法,即没人能证明有解开的方法,就能说明没有方法:)
结果是否定,方法是反证法,即没人能证明有解开的方法,就能说明没有方法:)
#21
//n,m
//没那么复杂吧?不就是二路归并算法么?
int nList[n], ans[n];
int i,j,k;
for(i=0,j=m,k=0; i<m&&j<n; k++)
{
if(nList[i]>nList[j])
{
ans[k] = nList[i];
i++;
}
else
{
ans[k] = nList[j];
j++;
}
}
if(i<m)
{
for(;i<m; i++,k++)
{
ans[k] = nList[i];
}
}
else
{
for(;j<n; j++,k++)
{
ans[k] = nList[j];
}
}
//ans为排序后结果
/如果算上ans空间, 那应该是O(n),o(n)
http://www.ohyee.net
//没那么复杂吧?不就是二路归并算法么?
int nList[n], ans[n];
int i,j,k;
for(i=0,j=m,k=0; i<m&&j<n; k++)
{
if(nList[i]>nList[j])
{
ans[k] = nList[i];
i++;
}
else
{
ans[k] = nList[j];
j++;
}
}
if(i<m)
{
for(;i<m; i++,k++)
{
ans[k] = nList[i];
}
}
else
{
for(;j<n; j++,k++)
{
ans[k] = nList[j];
}
}
//ans为排序后结果
/如果算上ans空间, 那应该是O(n),o(n)
http://www.ohyee.net
#22
O(n),o(n)?
你每看清题目还是没戴眼睛?
你每看清题目还是没戴眼睛?
#23
100分买一个2路归并的算法
#24
补充一下,如果问题是:
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
===============================
如果 m = k = 1,那么……
现有一个数组,长度为n,其前m个元素和后k个元素都已经排序过了。求时间复杂度O(n),空间复杂度O(1)的算法。
===============================
如果 m = k = 1,那么……
#25
to lzf_china(岁月如歌)
是在同一个数组原地排序,不是二路归并。
嗯,看来不得不承认 0000000009(韩雷)的诡辩了。。。
明天就结帖
是在同一个数组原地排序,不是二路归并。
嗯,看来不得不承认 0000000009(韩雷)的诡辩了。。。
明天就结帖
#26
题目不清,有点像华为的作风。基本上猜题就让你累个半死,然后还以此来鄙视你的专业水平不行。嘿嘿。这种题目有N种可能性,既可能有解,也可能没解。他要说简单,就是二路归并嘛,找个数空余数组,两个指针,完事。他要说不简单,就非说这个题没解。怎么说都是对的,你拿他没撤。呵呵