百度面试题,假设一整型数组存在若干正数和负数,现在通过某种算法使得该数组的所有负数在正数的左边,且保证负数件和正数间元素相对位置不变。时空复杂度要求分别为:o(n),o(1)
例如
-3 4 2 -1 7 3 -5
排序后
-3 -1 -5 4 2 7 3
这个题是别人问的,在开始也太看清题目,感觉像acm的题,这很好实现嘛,用快排的思想,但是一想不行呀,要保持相对位置不变,于是想到在定义一个数组,但是这样空间复杂度又变了,要是用其他的方法的话时间复杂度最少也是O(n2)。于是我仔细的分析了下这个题:
要是数组的话,就必须移动相对元素,时间复杂度肯定要上去,在定义一个数组还不行,所以这时候能让我考虑到的就只有存储结构改变一下了,如果用链表的话 就可以了,因为链表改变元素位置,并不需要移动其他元素只需要将指针改下,这样时间复杂度就下来了。显然这种方法是可以的。如果真是这样,这个面试题考的就没有生命技术含量,只要考察人分析问题的能力。
后来我仔细看了一个其实不用数组也完全可以实现,想通了其实很简单:就是将第一个负数插到第一个整数的前面,只要把第一个整数和第一个负数之间的元素向后移动一个位置,然后将第一个负数加入到原来第一个整数的位置,然后就可以了,只要遍历一次,代码如下:
#include <stdio.h>
/***********************************************
*函数名insertSort
*函数功能:分离正负数并保持其相对位置不变
*交流群:162369980
*作者:痞少
**********************************************/
void insertSort(int*A ,int size)
{
int minus=-1,plus=-1;
int tmp=0;
for(int i=0;i<size;i++)
{
if(minus==-1)
{
if(A[i]<0&& plus>=0)
{
minus=i;//用来寻找第一个负数
}
if(A[i]>0&& plus<0)
{
plus=i;//用来寻找第一个整数
}
}
if(minus>=0&& plus>=0)//都找到之后进行交换
{
tmp=A[plus];
A[plus++] = A[minus];
for (int k = minus; k> plus; k--)
{
A[k] = A[k -1];
}
A[plus]=tmp;
minus=-1;
}
}
}
/*************测试用例****************/
int main(void)
{
int a[] = {2,3,-2,4,5,-3,-4,-5}, len, i;
len = sizeof(a)/sizeof(int);
for(i = 0; i < len; i++)
printf("%d ", a[i]);
printf("\n");
insertSort(a , len);
for(i = 0; i < len; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
目前只想到这两种方法,如果大家还有什么其他方法的话可以加入群里进行交流,如有错误欢迎大家提出。