面试题14:调整数组顺序使奇数在偶数前面
2016-06-04 10:28
393 查看
题目:输入一个整数数组,实现一个函数来调整数组中数字的顺序,使得奇数位于数组的前半部分,偶数位于数组的后半部分。
咋一看,没有限定空间复杂度,直接想到声明两个数组,一个存奇数,一个存偶数。再合并。时间复杂度O(n),空间复杂度O(n),代码如下:
再看一下题目,发现我一开始就跑偏了,我开始想的是数组以前元素的相对顺序不变,结果看本题好像没有这个意思,那就更简单了。
采用两个指针,一个指向数组的开头,一个指向数组的结尾。当开头的指针遇到奇数,跳过,遇到偶数,停止,指向数组末尾的指针遇到偶数,跳过,遇到奇数,停止。然后两个指针交换元素。这种思想类似于快速排序中的partition思想。算法原地调整,时间复杂度O(n),空间复杂度O(1).
先试着写个。
看网上有人为了使算法具有稳定性,采用归并排序,可是归并排序要的空间复杂度就是O(n),有那个O(n)还不如直接像开始一样声明两个数组呢。
想到腾讯今年的实习笔试,有一道类似的题目,但是是要求空间复杂度是O(1),那没办法,只有牺牲时间复杂度了。
代码如下:
咋一看,没有限定空间复杂度,直接想到声明两个数组,一个存奇数,一个存偶数。再合并。时间复杂度O(n),空间复杂度O(n),代码如下:
class Solution { public: void reOrderArray(vector<int> &array) { vector<int> oddArray; vector<int> evenArray; int i; for(i=0;i<array.size();i++) { if(array[i]%2==1) { oddArray.push_back(array[i]); } else evenArray.push_back(array[i]); } for(i=0;i<oddArray.size();i++) { array[i]=oddArray[i]; } for(i=0;i<evenArray.size();i++) { array[oddArray.size()+i]=evenArray[i]; } return ; } };面试时感觉这种肯定过不了。考虑下节省空间复杂度。
再看一下题目,发现我一开始就跑偏了,我开始想的是数组以前元素的相对顺序不变,结果看本题好像没有这个意思,那就更简单了。
采用两个指针,一个指向数组的开头,一个指向数组的结尾。当开头的指针遇到奇数,跳过,遇到偶数,停止,指向数组末尾的指针遇到偶数,跳过,遇到奇数,停止。然后两个指针交换元素。这种思想类似于快速排序中的partition思想。算法原地调整,时间复杂度O(n),空间复杂度O(1).
先试着写个。
class Solution { public: void reOrderArray(vector<int> &array) { int i=0,j=array.size()-1; while(i<=j) { while(i<array.size()&&array[i]%2==1) i++; while(j>=0&&array[j]%2==0) j--; if(i<=j) swap(array[i],array[j]); } return; } };不过快速排序本身就是不稳定的排序方法,这种方法虽然奇数在前,偶数在后,但是肯定数组的元素相对顺序和以前不同。如1,2,3,4,5肯定变成了1,5,3,4,2.
看网上有人为了使算法具有稳定性,采用归并排序,可是归并排序要的空间复杂度就是O(n),有那个O(n)还不如直接像开始一样声明两个数组呢。
想到腾讯今年的实习笔试,有一道类似的题目,但是是要求空间复杂度是O(1),那没办法,只有牺牲时间复杂度了。
代码如下:
class Solution { public: void reOrderArray(vector<int> &array) { int len=array.size(),i,j,k,l; for(i=len-1,j=len-1;i>=0&&j>=0;) //i,j分别代表最前的一个偶数,奇数指针 { if(array[i]%2==0) //当前为偶数,直接跳过 { i--; j--; } else { for(k=j-1;k>=0;) //当前array[i]是奇数,寻找下一个偶数,再将偶数和后面所有的不是偶数的都交换 { if(array[k]%2==1) k--; else { int temp=array[k]; memcpy((char *)(&array[k]),(char *)(&array[k+1]),sizeof(int)*(i-k)); array[i]=temp; break; /* for(l=k;l<i;l++) { swap(array[l],array[l+1]); } break;*/ } } i=i-1; //更新偶数指针 j=k; //更新奇数指针 } } } };本算法理论上时间复杂度O(n*n*n),但是实际肯定不到。思考用内存拷贝,会快点,理论时间复杂度为O(n*n).
相关文章推荐
- 算法 剑指Offer 面试题32 从1到n整数中1出现的次数
- 为什么开源可以提高程序员的编程技能?
- 4月面试总结
- Java程序员应该掌握
- Java程序员的日常 —— 多进程开发IO阻塞问题
- 诚信与职业道德
- 0603 职业道德--软件工程
- 优秀程序员有哪些秘诀
- 学术诚信与职业道德
- 一个工作一年半的程序员的自述(三)
- 剑指Offer----面试题15:链表中倒数第K个结点
- 一些前端开发面试题
- 北航面试之离散数学
- 程序员如何谋划出月薪3万
- 程序求1!+2!+3!+...+1000!的和, 求1到1000阶乘之和
- 学术诚信与职业道德
- 学术诚信与职业道德 感受
- 程序猿的转型
- 第二个冲刺:学术诚信与职业道德
- 学术诚信与职业道德