免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 12325 | 回复: 66
打印 上一主题 下一主题

挑战数组腾挪大法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2002-10-22 20:23 |只看该作者 |倒序浏览
[这个贴子最后由samhoo在 2002/10/28 12:04pm 编辑]

问题:给定一个数组long L[1000],且已知X是其中的一个元素,如何使得小于X的元素位于数组左边,大于X的元素位于数组右边,并得到X在数组中的下标。

要求:1)如何不使用额外的数组;2)时间复杂度不大于O(n)

有没有办法做到呢?

--------------------------修改--------------------------------------------------

题目:给定一个数组long L[n],且已知X是其中的一个元素(等于X的元素可能不止一个),如何使得小于X的元素位于数组左边,大于X的元素位于数组右边,并得到X在数组中的下标。
要求:1)如何不使用额外的数组;2)时间复杂度不大于O(n)

提示:
A)为了能使讨论能集中于算法本身,而不是无关主旨的细节,下面附上模板程序,只需实现Partition函数即可验证程序是否正确。
B)如果大家能遵守一定的“八股”,我们沟通的效率会高些。(事实上,没有多少人可以有耐心看别人的代码,能看看算法以及测试结果就不错了,下面的“八股”直面这一事实)


八股:
一)算法说明
二)编译运行平台,机器类型/主频
三)Partition函数代码
四)至少给出前4组测试数据的结果
  i  )L[]={5,5,5,5,5,5,7,1,6,8}&#59; n=10&#59; X=5&#59; (在main函数提供,注释掉其中一些语句即可)
  ii )n=10的随机数组
  iii)n=10,000,000的随机数组
  iv )n=50,000,000的随机数组(小心,别影响别人工作)
  v  )其他自己认为具有“边界”特性的数组。


模板程序:
#include<string.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<time.h>;

#define DISPLAY \
  { \
  int i&#59; \
  printf(&quot;L[]=&quot&#59; \
  for (i = 0&#59; i < num&#59; i++){ \
     if (i >; 20 ){ \
         printf(&quot;...(too much number, ignore)&quot&#59; \
         break&#59; \
     } \
     printf(&quot;%d &quot;, L)&#59; \
  } \
  printf(&quot;\n&quot&#59; \
  }


int  Partition(long *L, int n, long X)&#59;  /* 实现这个函数 */
long *MakeRandomList(int *num)&#59;
long *CreateList(int n)&#59;
int  Check(long *L, int num, int X, int position)&#59;
int  SWAP(long *L, int a, int b)&#59;

int main()
{
long X&#59;
long *L&#59;
//long L[]={5,5,5,5,5,5,7,1,6,8}&#59;
int  num = 10&#59;
int  pos = 0&#59;
clock_t start_time, end_time&#59;
double  duration&#59;


L=MakeRandomList(&amp;num)&#59;
X = L[(num - 1) / 2]&#59;

printf(&quot;X=%ld\n&quot;, X)&#59;
DISPLAY
printf(&quot;-----------------------------------------------------------------\n&quot&#59;

start_time=clock()&#59;  
pos = Partition(L, num, X)&#59;
end_time=clock()&#59;

printf(&quot;Check :&quot&#59;  
if (Check(L, num, X, pos))
     printf(&quot;incorrect.\n&quot&#59;
else
     printf(&quot;correct.\n&quot&#59;
     
duration = (double)(end_time - start_time) / CLOCKS_PER_SEC&#59;
printf(&quot;Time  : %.3f seconds.\n&quot;, duration)&#59;

printf(&quot;-----------------------------------------------------------------\n&quot&#59;
printf(&quot;position=%ld\n&quot;, pos)&#59;
DISPLAY

free(L)&#59;
return 0&#59;
}


/*
* L:输入数组
* n:数组大小
* X:X元素
* 返回X在数组中的下标
*/
int  Partition(long *L, int n, long X)
{
//在这里插入你的代码
}


long *CreateList(int n)
/* Allocates memory for an array of n longs */
{
long *L&#59;

L = (long *) malloc( n * sizeof(long) )&#59;
if( L == NULL) { /* Exit program if memory cannot be allocated */
    printf(&quot;\nCannot allocate enough memory for list.\n&quot&#59;
    exit(0)&#59;
}

return (L)&#59;
}

long *MakeRandomList(int *num)
{
long *L&#59;               /* pointer to List */
unsigned int seed&#59;     /* seed for random number generator */
int i&#59;                 /* index of for loop */

printf(&quot;\nNumber of elements to sort=>;&quot&#59;
scanf(&quot;%d&quot;,num)&#59;

printf(&quot;Seed for random number generator (integer)=>;&quot;)&#59;
scanf(&quot;%d&quot;,&amp;seed)&#59;
srand(seed)&#59;

/* Allocate memory for # of elements. If memory cannot be allocated,
    display message and terminate program. Read in the elements. */
L = CreateList(*num)&#59;
if (L == NULL) {
    printf(&quot;\nCannot allocate enough memory for number list.\n&quot;)&#59;
    exit(0)&#59;
}
for (i = 0&#59; i < *num&#59; ++i)
    L = rand()&#59;

return(L)&#59;           /* Return the List */
}

int Check(long *L, int num, int X, int position)
{
int i, lpos = -1, rpos = -1&#59;

for (i = 0&#59; i < num&#59; i++)
   if (L == X){
     lpos = i&#59;
     break&#59;
   }
   else if (L >; X)
     return -1&#59;

for (i = num - 1&#59; i >;= 0&#59; i--)
   if (L == X){
     rpos = i&#59;
     break&#59;
   }
   else if (L < X)
     return -1&#59;
           
if ((lpos == -1) || (rpos == -1) || (position < lpos) || (position >;rpos))
   return -1&#59;

for (i = lpos&#59; i <=rpos&#59; i++)
   if (L != X)
     return -1&#59;

return 0&#59;
}

int SWAP(long *L, int a, int b)
{
long temp&#59;

temp = L[a]&#59;
L[a] = L&#59;
L = temp&#59;
return 0&#59;
}

论坛徽章:
0
2 [报告]
发表于 2002-10-23 09:08 |只看该作者

挑战数组腾挪大法

将数组进行排序不就行了吗!

论坛徽章:
0
3 [报告]
发表于 2002-10-23 10:55 |只看该作者

挑战数组腾挪大法

题目没有强调效率,而只是空间要求,确实是漏洞。但如果加上条件:时间复杂度为O(n)。
如何?

论坛徽章:
0
4 [报告]
发表于 2002-10-23 14:36 |只看该作者

挑战数组腾挪大法

想了一天了.想不出什么办法.
binary tree 吧相当于用了空间.时间复杂度也不是O(n)
Shell排序可能可以完成,不过也要在原始数据分步比较合你的意思的时候才有可能达到O(n).

你有什么算法拿来看看.不要卖关子了..

要是没有....................哼哼...哼哼哼......哼哼哼哼.......................................拿弹弓打你们家玻璃.

论坛徽章:
0
5 [报告]
发表于 2002-10-23 15:04 |只看该作者

挑战数组腾挪大法

我没有解决这个问题,

也许我把问题的来源说出来更能让各位拓宽思路:这个问题是在我替在米国的朋友捉刀的时候,衍生出来的问题:实现Selection in Worst-Case Linear Time(不知道中文译名)。算法描述见http://www.cs.fsu.edu/~burmeste/slideshow/chapter10/10-3.html

其中说的modified version of Partition算法和我出的题目也一样了。
当时时间紧迫,就用了与原数组一样大的空间,但无也须排序:
int Partition(long *L, int first, int last, long X)
{
   long *P&#59;
   int i&#59;
   int iLeft = 0&#59;
   int iRight = last - first&#59;

   P = CreateList(last - first + 1)&#59;
   for (i = first&#59; i <= last&#59; i++){
      if (L < X){
         comparison_count++&#59;
         P[iLeft] = L&#59;
         iLeft++&#59;
      }
      else if (L >; X){
         comparison_count++&#59;
         P[iRight] = L&#59;
         iRight--&#59;
      }
   }
   for (i = iLeft&#59; i <= iRight&#59; i++)
      P = X&#59;

   for (i = first&#59; i <= last&#59; i++)
      L = P[i - first]&#59;
   free(P)&#59;

   return iRight + first&#59;
}




论坛徽章:
8
申猴
日期:2014-01-01 22:11:07白羊座
日期:2014-11-18 20:53:022015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之四川
日期:2016-01-19 18:39:36综合交流区版块每日发帖之星
日期:2016-06-07 06:20:0015-16赛季CBA联赛之广东
日期:2016-10-30 11:34:40CU十四周年纪念徽章
日期:2016-11-13 10:06:5715-16赛季CBA联赛之同曦
日期:2022-08-28 15:58:19
6 [报告]
发表于 2002-10-23 19:26 |只看该作者

挑战数组腾挪大法

可以办得到啊!
void specsort(long L[],int pos){
int i,j,tmp1,tmp2=999&#59;
for(i=0&#59;i<1000&#59;i++){
if(L>;X){
for(j=tmp2&#59;j<i&#59;j--){
if(L[j]<x){
tmp=L[j]&#59;
L[j]=L&#59;
L=tmp&#59;
tmp2=j&#59;
break&#59;
}
}
if(j==i) break&#59;
}
else if(L==x) pos=i&#59;
}
}
}

论坛徽章:
8
申猴
日期:2014-01-01 22:11:07白羊座
日期:2014-11-18 20:53:022015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之四川
日期:2016-01-19 18:39:36综合交流区版块每日发帖之星
日期:2016-06-07 06:20:0015-16赛季CBA联赛之广东
日期:2016-10-30 11:34:40CU十四周年纪念徽章
日期:2016-11-13 10:06:5715-16赛季CBA联赛之同曦
日期:2022-08-28 15:58:19
7 [报告]
发表于 2002-10-23 19:28 |只看该作者

挑战数组腾挪大法

有点问题!改后!:
void specsort(long L[],long X,int pos){
int i,j,tmp1,tmp2=999&#59;
for(i=0&#59;i<1000&#59;i++){
if(L>;X){
for(j=tmp2&#59;j<i&#59;j--){
if(L[j]<x){
tmp=L[j]&#59;
L[j]=L&#59;
L=tmp&#59;
tmp2=j&#59;
break&#59;
}
}
if(j==i) break&#59;
}
else if(L==x) pos=i&#59;
}
}
}

论坛徽章:
0
8 [报告]
发表于 2002-10-23 20:51 |只看该作者

挑战数组腾挪大法

wwjxjtu:
你的思路其实和插入排序无异,时间复杂度为O(n^2),难以接受。
而且实现也是有问题的:
如:        L[]=2 7 9 6 4
最后调整后的L[]=2 7 4 6 9, pos = 1&#59;
不符合要求。

论坛徽章:
0
9 [报告]
发表于 2002-10-23 23:30 |只看该作者

挑战数组腾挪大法

samhoo
我觉得你的算法反正要用空间,还不如用bintree实现来得容易

论坛徽章:
0
10 [报告]
发表于 2002-10-24 09:33 |只看该作者

挑战数组腾挪大法

我的想法是:该题目要求的信息其实只是分开大小这样的弱信息,而排序这样的强信息对它来说确实是太浪费。

有解吗?条件是:1)不能分配随n增加而增大的空间;2)算法复杂度不超过O(n)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP