面试题:删除有序数组中的重复元素,空间复杂度O(1),时间复杂度尽可能低

laomai 2004-01-18 10:54:43
今天和高手讨论(其实应该是请教,呵呵)一道面试题目:
一串排序过的数字,空间复杂度O(1),删除重复的数字。
我写了一个,自认为比较优雅,时间复杂度O(N*n),还沾沾自喜。
可是一看高手的算法,写的那叫简洁,那叫幽雅
令我只有佩服和赞叹的份。
再此我先不写答案,看看弟兄们对这道题的解答是什么?
凡是比高手的‘答案还简洁的,给100分,呵呵。另一百分送给那位高手,以表敬意:-)
...全文
1048 80 打赏 收藏 转发到动态 举报
写回复
用AI写文章
80 条回复
切换为时间正序
请发表友善的回复…
发表回复
flyr99 2004-01-31
  • 打赏
  • 举报
回复
今天和高手讨论(其实应该是请教,呵呵)一道面试题目:
一串排序过的数字,空间复杂度O(1),删除重复的数字。
我写了一个,自认为比较优雅,时间复杂度O(N*n),还沾沾自喜。
可是一看高手的算法,写的那叫简洁,那叫幽雅
令我只有佩服和赞叹的份。
再此我先不写答案,看看弟兄们对这道题的解答是什么?
凡是比高手的‘答案还简洁的,给100分,呵呵。另一百分送给那位高手,以表敬意:-)



搂住什么时候把答案写出来,让大家分享一下。
zhllg 2004-01-31
  • 打赏
  • 举报
回复
不好意思啊,上面的main不太对,下面的没有问题了
main(int argc, char *argv[]){
int i, j, value[argc];

if(argc < 2){
printf("Usage: trim 0 2 3 4 4.....\n");
return;
}

for(j = 1; j < argc; j++)
value[j-1] = atoi(argv[j]);

i = trim(value, --argc);

for(j = 0; j < i; j++)
printf("%d\n", value[j]);

return 0;
}
zhllg 2004-01-31
  • 打赏
  • 举报
回复
int trim(int value[], int length);

main(int argc, char *argv[]){
int i, j, value[argc];

if(argc < 2)
perror("Usage: trim 0 2 3 4 4.....");

for(j = 0; j < argc; j++)
value[j] = atoi(argv[j]);

i = trim(value, argc);

for(j = 0; j < i; j++)
printf("%d\n", value[j]);

return 0;
}

int trim(int value[], int length){
int i, k=0;

for(i = 1; i < length; i++){
if(value[i] == value[k])
continue;
value[++k] = value[i];
}
return ++k;
}
wonita 2004-01-25
  • 打赏
  • 举报
回复
up
flyr99 2004-01-25
  • 打赏
  • 举报
回复
另一个类似问题,条件跟题目一样,求出一个数组中出现频率最高的数字,也就是mode,最好不要借用STL的算法函数,程序尽量简洁,效率尽可能高
flyr99 2004-01-24
  • 打赏
  • 举报
回复
楼上的高手,你的分析很精彩,帮忙分析一下我写的,有哪些问题,顺便问一下你的QQ号,或者是MSN是多少,互相交流一下
flyr99 2004-01-24
  • 打赏
  • 举报
回复
//bug fix
#include <iostream>

int removeDuplicate( int* source, const int size )
{
int curPos = 1;
for( int i = 1; i < size; i++ )
if( source[i] != source[i-1] ) source[curPos++] = source[i];
return size <= 0 ? 0 : curPos;
}

int main( int argc, char** args )
{
int numbers[] = { 2, 3, 3, 3, 5, 5, 6, 6, 6, 7, 7, 9 };

for( int i = 0, curPos = removeDuplicate( numbers, sizeof(numbers)/
sizeof(int) ); i < curPos; i++ )
std::cout << numbers[i] << " ";

return 0;
}
laomai 2004-01-24
  • 打赏
  • 举报
回复
呵呵,看来我的砖效果还可以,引出不少玉来。
希望大家继续讨论,我的感觉可以用四个字来形容“收益非浅”
漂流的代码 2004-01-24
  • 打赏
  • 举报
回复
对不起,少了一个}
漂流的代码 2004-01-24
  • 打赏
  • 举报
回复
献丑了:
int RemoveSame(int arr[],int max)
{
assert(arr!=NULL);
int i=1;
while(i<max)
{
if(arr[i-1]==arr[i])
{
int j=i;
while(j<max-1) arr[j]=arr[j+1];
}
else
i++;
}
leqian 2004-01-24
  • 打赏
  • 举报
回复
可以用泛型算法
unique()
template< class ForwardIterator >
ForwardIterator
unique( ForwardIterator first,
ForwardIterator last );
template< class ForwardIterator, class BinaryPredicate >
ForwardIterator
unique( ForwardIterator first,
ForwardIterator last, BinaryPredicate pred );
对于连续的元素如果它们包含相同的值使用底层类型的等于操作符来判断或者
把它们传给pred 的计算结果都为true 则这些元素被折叠成一个元素例如在单词mississippi
中语义上的结果是misisipi 注意四个i 不是连续的所以不会被折叠类似地因为两
对s 也是不连续的所以也没有被折叠成单个实例为了保证所有重复的实例都被折叠起来
我们必须先对容器进行排序

以下是我写的。

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;

void main()
{
int ia[10]={1,1,3,4,4,4,66,67,67,67};
vector< int > ivec(ia, ia+10);
vector< int >::iterator vec_iter;

vec_iter = unique( ivec.begin(), ivec.end() );

for(vector<int>::iterator i=ivec.begin(); i!=vec_iter; ++i)
{
cout<<*i<<' ';
}
}
因为我是学生,顺便问一下,stl在实际开发中用的多不多?
superman421 2004-01-24
  • 打赏
  • 举报
回复
人家都已经作的很好了怎么还有那么多的人不停的发???????
算法吗表意就行了!
haoyangmao8 2004-01-24
  • 打赏
  • 举报
回复
用STL
flyr99 2004-01-24
  • 打赏
  • 举报
回复
//more robust, more efficient, more clear, more powerful, but shorter code
//sorry about those english, I could not type chinese at school
//my contect QQ number : 14012040, email : ren_goa@hotmail.com

#include <iostream>

int removeDuplicate( int* source, const int size )
{
int curPos = 1;
for( int i = 1; i < size; i++ )
if( source[i] != source[i-1] ) source[curPos++] = source[i];
return size <= 0 ? 0 : curPos;
}

int main( int argc, char** args )
{
int numbers[] = { 2, 3, 3, 3, 5, 5, 6, 6, 6, 7, 7, 9 };

for( int i = 0, cusPos = removeDuplicate( numbers, sizeof(numbers)/
sizeof(int) ); i < curPos; i++ )
std::cout << numbers[i] << " ";

return 0;
}
flyr99 2004-01-24
  • 打赏
  • 举报
回复
//second improvement 清高手指点

#include <iostream>

//remove duplicates data from a source array
int removeDuplicate( int* source, const int size )
{
int curPos = 1; //position with no duplicate data
for( int i = 1; i < size; i++ )
if( source[i] != source[i-1] ) source[curPos++] = source[i];
//return 0 if size <=0 otherwise return position with no duplicate data
return size <= 0 ? 0 : curPos;
}

int main( int argc, char** args )
{
int numbers[] = { 2, 3, 3, 3, 5, 5, 6, 6, 6, 7, 7, 9 };

int curPos = removeDuplicate( numbers, sizeof( numbers ) / sizeof( int ) );

for( int i = 0; i < curPos; i++ )
std::cout << numbers[i] << " ";
std::cout << std::endl;

return 0;
}
flyr99 2004-01-24
  • 打赏
  • 举报
回复
这样比较好,上面那样写是因为超长了看起来不整齐
//return 0 if size is invalid otherwise return position with no duplicate data
//return 0 if size is a invalid number otherwise return position with no duplicate data
flyr99 2004-01-24
  • 打赏
  • 举报
回复
发个改良版 清高手指点
#include <iostream>
using namespace std;

//remove duplicates data from a source array
int removeDuplicate( int* data, const int );

int main( int argc, char** args )
{
const int arraySize = 12;
int numbers[arraySize] = { 2, 3, 3, 3, 5, 5, 6, 6, 6, 7, 7, 9 };

int curPos = removeDuplicate( numbers, arraySize );

for( int i = 0; i < curPos; i++ )
cout << numbers[i] << " ";
cout << endl;

cin.get();

return 0;
}

int removeDuplicate( int* source, const int size )
{
int curPos = 1; //position with no duplicate data
for( int i = 1; i < size; i++ )
if( source[i] != source[i-1] ) source[curPos++] = source[i];
//return 0 if size <=0 otherwise return position with no duplicate data
return size <= 0 ? 0 : curPos;
}
chinajiji 2004-01-23
  • 打赏
  • 举报
回复
#include <iostream>
#include <cstdlib>
using namespace std;

int unique(int *source, const int length) {
int pos = 0;
int i;
if(length <= 0) return 0;
for(i = 1; i < length; i++) {
if(!pos) {
if(source[i] == source[i - 1])
pos = i;
}
else if(source[i] != source[i - 1])
source[pos++] = source[i];
}
return pos ? pos : length;
}

int main() {
int data[] = {0, 1, 1, 2, 3, 4, 4, 4, 4, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11,12,};
// int data[] = {0, 0, 0, 0,};
// int data[] = {9, 8, 7, 6, 5,};
int length = unique(data, sizeof(data) / sizeof(int));
for(int i = 0; i < length; i++)
cout << data[i] << ' ';
cout << endl;
system("pause");

return 0;
}
chinajiji 2004-01-23
  • 打赏
  • 举报
回复
先一分析分析"老迈"给出的那个"简洁"算法:
void RemoveSame(int value[], int &num)
{
int k=0;
for(int i=1; i<num; i++)
{
if(value[i] != value[i-1])
{
value[++k] = value[i];
}
}
num = ++k;
}
问题一:
函数接口参数不妥:
void RemoveSame(int value[], int &num)
用int &num作为数组大小的参数,并将去掉重复数后数组大小值通过num回传给用户.
这样不妥,限制了调用RemoveSame()时,第2个参数必须是一个变量,如果是常量则不行,比如:
RemoveSame(source, sizeof(source)/sizeof(int));或RemoveSame(source, 5)这样调用这不行.但在实践中用户想如上调用ReomveSame()函数的时候是很多的.
RemoveSame()函数修改了传入参数num,但实际应用中,用户往往不候这个参数被修改.
所以,RemoveSame()函数原型最好这样:
int unique(int source[], int length);
或int unique(int source[], size_t length);

问题二
函数名RemoveSame()是典型的"Chinese-English",且第一个字母按习惯不应大写.

问题三
对第个参数int &num没有进行参数合法取值范围检测,当num <= 0时,结果出错.

问题三
最坏情况下,当n个元素仅在最后一个元素出现重复时,将多运行n-1次赋值语句:value[++k] = value[i];

题外话:这类问题,首先想到的应该是用线型链表来解决,而不是数组.

KingI 2004-01-23
  • 打赏
  • 举报
回复
#include <stdio.h>
#define N 6
main()
{
int a[N],b[N],i,j,k=0;
printf ("Input %d numbers:\n",N);
for (i=0; i<N; i++)
scanf ("%d",a+i);
for (i=0; i<N; i++)

for (j=i+1; j<N; j++)
{
if (a[i]==a[j])
{
a[i]=0;
a[j]=0;

}

}
for (i=0; i<N; i++)
{if (a[i]==0) continue;
b[k++]=a[i];
}
if (k==0) printf("All number have been delete!");
else
{
for (i=0; i<k; i++)
printf ("%2d",b[i]);
}

}
加载更多回复(60)

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧