程序员面试题目总结--数组(四)【数列中符合条件数对的个数、数组是否存在重复元素、重新排列数组使数组左边为奇数,右边为偶数、数组中的第二大数、数组中的最小值和最大值】
2014-07-31 16:00
696 查看
16、找出数列中符合条件的数对的个数
题目:一个整型数组,元素取值可能为1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现,找出数列中符合条件的数对的个数,满足数对中两数的和为N+1
分析:先对数组进行排序,然后使用二分查找方法,用两个指针分别指向第一个和最后一个元素,然后从两端同时向中间遍历,直到连个指针交叉。
(1)如果A[front]+A[back]>N+1 则back--
(2)如果A[front]+A[back]=N+1 则计数器加1,back--,同时front++
(3)如果A[front]+A[back]<N+1 则front++
引申:已知大小分别为m,n的两个无序数组A,B和一个常数C,求满足A[i]+B[j]=C的所有A[i]和B[j]
方法1:排序+线性扫描法,对A和B进行排序,然后用指针P从头扫描A,用指针q从尾扫描B,
如果A[P]+B[q]==c 则输出A[p]和B[q],且p++,q--;如果A[P]+B[q]>c,则q--;否则p++ ( O(mlogm+nlongn) )
17、判定数组是否存在重复元素
题目:假设数组a有n个元素,元素取值范围为1~n,如何判定数组是否存在重复元素
分析:
方法一:对数组进行排序,然后比较相邻的元素是否相同。 时间复杂度O(nlogn)
18、重新排列数组使得数组左边为奇数,右边为偶数
题目:给定一个整型数组,如何重新排列数组使得数组的左边为奇数,右边为偶数。 要求时间复杂度为O(N),空间复杂度为O(1)
分析:类似快速排序,可以用两个指针分别指向数组的头和尾。头指针正向遍历数组,找到第一个偶数,尾指针逆向遍历数组,找到第一个奇数,交换两个指针指向的数字,然后两个指针继续移动直到头指针大于等于尾指针为止
19、找出数组中的第二大数
题目:找出数组中的第二大数
分析: 只通过一次遍历求出数组中的第二大数,通过设置两个变量来进行判断,首先定义一个变量来存储数组的最大数,初始值是数组首元素,另一个变量存储第二大数,初始值为最小负数,然后遍历数组元素,如果数组元素比最大值变量大,则将第二大变量的值设为最大数变量的值,最大数变量的值为该元素,如果比最大值小,则和第二大值比较;如果大,则更新第二大数的值为该数组元素的值
注: 上式 const int MINNUM = -2147483647-1 写成 const int MINNUM = -2147483648 会有警告
原因如下:一元负运算符应用于无符号类型,结果仍为无符号类型。无符号类型只能保存非负值,所以一元负(非)应用于无符号类型时通常无意义。操作数和结果都是非负的。 实际上,当程序员试图表达最小整数值-2147483648 时,发生此问题。该值不能写为-2147483648,因为表达式处理分两个步骤: 计算数字2147483648。因为2147483648 大于最大整数值2147483647,所以其类型不是int,而是unsigned int。
参考链接:http://blog.csdn.net/adupt/article/details/4503516
20、寻找数组中的最小值和最大值
题目:寻找数组中的最小值和最大值
分析:
方法一:维持两个变量min和max,min标记最小值,max标记最大值,每次比较相邻两个数,较大者与max比较,较小者与min比较,找出最大值和最小值
题目:一个整型数组,元素取值可能为1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现,找出数列中符合条件的数对的个数,满足数对中两数的和为N+1
分析:先对数组进行排序,然后使用二分查找方法,用两个指针分别指向第一个和最后一个元素,然后从两端同时向中间遍历,直到连个指针交叉。
(1)如果A[front]+A[back]>N+1 则back--
(2)如果A[front]+A[back]=N+1 则计数器加1,back--,同时front++
(3)如果A[front]+A[back]<N+1 则front++
void FixedSum(int a[],int n,int d) { for(int i=0,j=n-1;i<n && j>=0 && i<j;) { if(a[i]+a[j] <d) ++i; else if(a[i]+a[j]==d) { cout << a[i] << ' ' << a[j] <<endl; ++i; --j; } else --j; } }
引申:已知大小分别为m,n的两个无序数组A,B和一个常数C,求满足A[i]+B[j]=C的所有A[i]和B[j]
方法1:排序+线性扫描法,对A和B进行排序,然后用指针P从头扫描A,用指针q从尾扫描B,
如果A[P]+B[q]==c 则输出A[p]和B[q],且p++,q--;如果A[P]+B[q]>c,则q--;否则p++ ( O(mlogm+nlongn) )
void Print_Pairs_With_Sum(int a[],int b[],int m,int n,int sum) { sort(a,a+m); sort(b,b+n); int p=0; int q=n-1; while(p<m && q>=0) { if(a[p]+b[q] == sum) { cout << '(' << a[p] <<',' << b[q] << ')' << endl; p++; q--; } else if(a[p]+b[q] > sum) q--; else p++; } }方法二:Hash法,首先将两个数组中较小的数组保存到HashTable中,然后,对于B中每个元素B[i],也采用相同的hash算法。在HashTable中查找c-B[i]是否存在,如果存在,则输出,时间复杂度:O(m+n)
void Print_Pairs_With_Sum2(int a[],int b[],int m,int n,int sum) { map<int,bool> hash_table; int *psmall=a; int *pbig=b; int nsmall=(m>=n) ? n :m; int nbig=(m>=n) ? m : n; if(m>n) { psmall=b; pbig=a; } for(int i=0;i<nsmall;i++) { hash_table.insert(pair<int,bool>(psmall[i],true)); } for(int i=0;i<nbig;i++) { if(hash_table.find(sum-pbig[i])!=hash_table.end()) cout << '(' << pbig[i] << ',' << sum-pbig[i] << ')' << endl; } }
17、判定数组是否存在重复元素
题目:假设数组a有n个元素,元素取值范围为1~n,如何判定数组是否存在重复元素
分析:
方法一:对数组进行排序,然后比较相邻的元素是否相同。 时间复杂度O(nlogn)
int isArrayRepeat(int a[],int n) { if(a==NULL || n <=0) return -1; sort(a,a+n); for(int i=0;i<n-1;i++) { if(a[i] == a[i+1]) return 1; } return 0; }方法二:遍历数组,假设第i个位置的数字为j,则通过交换将j换到下标为j的位置,直到所有的数字都出现在自己对应的下标处,或发生了冲突。时间复杂度为O(n)
int isArrayRepeat1(int a[], int n) { int i=0; int j=-1; for(i=0;i<n;i++) { j=a[i]; if(i==j) continue; if(a[i]==a[j]) return 1; a[i]=a[j]; a[j]=j; } return 0; }
18、重新排列数组使得数组左边为奇数,右边为偶数
题目:给定一个整型数组,如何重新排列数组使得数组的左边为奇数,右边为偶数。 要求时间复杂度为O(N),空间复杂度为O(1)
分析:类似快速排序,可以用两个指针分别指向数组的头和尾。头指针正向遍历数组,找到第一个偶数,尾指针逆向遍历数组,找到第一个奇数,交换两个指针指向的数字,然后两个指针继续移动直到头指针大于等于尾指针为止
void AdjustArray(int a[], int n) { int begin=0; int end=n-1; while(begin < end) { while(a[begin]%2 == 1 && begin < end) ++begin; while(a[end]%2 == 0 && begin < end) --end; swap(a[begin],a[end]); } }
19、找出数组中的第二大数
题目:找出数组中的第二大数
分析: 只通过一次遍历求出数组中的第二大数,通过设置两个变量来进行判断,首先定义一个变量来存储数组的最大数,初始值是数组首元素,另一个变量存储第二大数,初始值为最小负数,然后遍历数组元素,如果数组元素比最大值变量大,则将第二大变量的值设为最大数变量的值,最大数变量的值为该元素,如果比最大值小,则和第二大值比较;如果大,则更新第二大数的值为该数组元素的值
const int MINNUM = -2147483647-1; int FinfSecMax(int a[],int n) { int max=a[0]; int sec_max=MINNUM; for(int i=0;i<n;i++) { if(a[i] > max) { sec_max=max; max=a[i]; } else { if(a[i] > sec_max) sec_max=a[i]; } } return sec_max; }
注: 上式 const int MINNUM = -2147483647-1 写成 const int MINNUM = -2147483648 会有警告
原因如下:一元负运算符应用于无符号类型,结果仍为无符号类型。无符号类型只能保存非负值,所以一元负(非)应用于无符号类型时通常无意义。操作数和结果都是非负的。 实际上,当程序员试图表达最小整数值-2147483648 时,发生此问题。该值不能写为-2147483648,因为表达式处理分两个步骤: 计算数字2147483648。因为2147483648 大于最大整数值2147483647,所以其类型不是int,而是unsigned int。
参考链接:http://blog.csdn.net/adupt/article/details/4503516
20、寻找数组中的最小值和最大值
题目:寻找数组中的最小值和最大值
分析:
方法一:维持两个变量min和max,min标记最小值,max标记最大值,每次比较相邻两个数,较大者与max比较,较小者与min比较,找出最大值和最小值
void FindMaxAndMin(int a[], int n, int& max, int& min) { max=a[0]; min=a[0]; for(int i=1;i<n-1;i=i+2) { if(a[i]==a[i+1]) { if(a[i]>max) max=a[i]; if(a[i]<min) min=a[i]; } else if(a[i]>a[i+1]) { if(a[i]>max) max=a[i]; if(a[i+1]<min) min=a[i+1]; } else if(a[i+1]>max) max=a[i+1]; if(a[i]<min) min=a[i]; } }方法二:分治法:将数组划分为两半,分别找出两边的最小值和最大值,则最大值,最小值分别是两边最小值的较小值、两边最大值的较大者
void FindMaxAndMin1(int a[],int begin,int end,int& max,int& min) { int k,max1,min1,max2,min2; if(end-begin == 1 || end-begin==0) a[begin] > a[end] ? (max=a[begin],min=a[end]) : (max=a[end],min=a[begin]); else { k=(begin+end)/2; FindMaxAndMin1(a,begin,k,max1,min1); FindMaxAndMin1(a,k+1,end,max2,min2); max=max1>max2 ? max1 : max2; min=min1<min2 ? min1:min2; } }
相关文章推荐
- 程序员面试题目总结--数组(一)【递归求数组所有元素和、用一个for循环打印出一个二维数组、用递归判断数组是否是递增、有序数组中删除重复元素】
- 程序员面试题目总结--数组(五)【数组的后面m个数移动为前面m个数、列的前n项数据、判断整数x是否可以表示成n个连续正整数的和、数组中出现奇数次的元素、二维数组中的查找】
- 程序员面试题目总结--数组(二)【二分查找、找出给定数字出现次数、两个有序整型数组交集、找出数组中唯一的重复元素、判断数组中的数值是否连续相邻】
- 题目:给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。
- 程序员面试题目总结--数组(三)【旋转数组的最小数字、旋转数组中查找指定数、两个排序数组所有元素中间值、数组中重复次数最多的数、数组中出现次数超过一半的数】
- 重新排列数组使得左边为奇数,右边为偶数
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。要求:空间复杂度O(1),时间复杂度为O(n)
- 重新排列数组,使得数组左边的数字为奇数,数组右边的数字为偶数
- 编程: 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。
- 重新排列数组使得数组左边为奇数,右边为偶数--方法三
- 重新排列数组使得数组左边为奇数,右边为偶数
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。 要求:空间复杂度O(1),时间复杂度为O(n)。
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数
- 4.给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。 要求:空间复杂度O(1),时间复杂度为O(n)
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数---百度笔试题