您的位置:首页 > 职场人生

程序员面试题目总结--数组(四)【数列中符合条件数对的个数、数组是否存在重复元素、重新排列数组使数组左边为奇数,右边为偶数、数组中的第二大数、数组中的最小值和最大值】

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++

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;
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐