【笔试面试】数组相关问题

//2015.08.10
/***  数组的若干问题
** 1 求数组的最值问题
** 2 求数组中出现次数超过总数一半的元素
** 3 两个有序数组的共同元素
** 4 两个有序数组中和为某一值得元素对
** 5 数组中只有某一元素出现基数次,求之
** 6 
**/

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

void printArry(vector<int> & arr)
{
	for (unsigned i=0;i<arr.size();++i)
	{
		cout<<arr[i]<<" ";
	}
	cout<<endl;
}

//求数组的最大值和最小值
void maxAndmin(vector<int> & arr,int &maxNum,int &minNum)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	if (!arr.size())
		return;
	maxNum = arr[0];
	minNum = arr[0];
	for (unsigned i=1;i<arr.size();++i)
	{
		if (arr[i] > maxNum)
			maxNum = arr[i];
		if (arr[i] < minNum)
			minNum = arr[i];
	}
	cout<<"此数组的最大值和最小值分别为:"<<maxNum<<ends<<minNum<<endl;
}

//求数组的最大值和次大值  若有两个最大值怎么办?
void maxAndNextmax(vector<int> & arr,int &maxNum,int &nextMaxNum)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	cout<<"数组的最大值和次大值分别为:"<<ends;
	if (arr.size()<2)
		return;
	maxNum = max(arr[0],arr[1]);
	nextMaxNum = min(arr[0],arr[1]);

	for (unsigned i=2;i<arr.size();++i)//若有两个最大值相等怎么办?
	{
		if (arr[i] > nextMaxNum )
		{
			nextMaxNum = arr[i];
			if (nextMaxNum > maxNum)
				swap(nextMaxNum,maxNum);
		}
	}
	cout<<maxNum<<ends<<nextMaxNum<<endl;
}

//求数组前最大的前k个数
int maxNumK(vector<int> & arr,int k)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	int m = arr.size();
	if (k > m)
	{
		cout<<"所求的个数比数组的元素多!error!!"<<endl;
		return 0; //设置全局变量 是否成功
	}
	int * temp = new int[k];
	for(int i=0;i<k;i++)
		temp[i] = arr[i];
	sort(temp,temp+k);
	for (unsigned i=k;i<arr.size();++i)
	{
		if (arr[i] > temp[0])
		{
			temp[0] = arr[i];
			sort(temp,temp+k);
		}
	}
	cout<<"数组的前k个最大的数是:"<<ends;
	//printArry(temp);
	for (int i=0;i<k;++i)
	{
		cout<<temp[i]<<" ";
	}
	cout<<endl;
	int num = temp[k-1];
	delete [] temp;
	return num;
}

//数组中出现次数超过一半的元素
int elementMulti(vector<int> & arr)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	int element = arr[0];
	int count =1;
	for (unsigned i =1;i<arr.size();++i)
	{
		if (arr[i]==element)
		{
			count++;
		}
		else
		{
			count--;
			if (count==0)
			{
				count = 1;
				element = arr[i];
			}
		}
	}
	cout<<"数组中出现次数超过一半的元素是:"<<element<<endl;
	return element;
}

//求数组中最短的距离
int minDistance(vector<int>  arr)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	sort(arr.begin(),arr.end());
	int  miniDist = arr[1]-arr[0];
	for(unsigned i=1;i<arr.size();++i)
		if (arr[i]-arr[i-1] < miniDist)
			miniDist = arr[i]-arr[i-1];
	cout<<"数组的最近的距离为:"<<miniDist<<endl;
	return miniDist;
}

//两个有序数组的共同元素
void common(vector<int> & arr1,vector<int> & arr2)
{
	cout<<endl<<"原始数组分别为:"<<endl;
	printArry(arr1);
	printArry(arr2);
	cout<<"两个数组的共同元素为:"<<ends;
	unsigned i = 0,j=0;
	while(i<arr1.size() && j<arr2.size())
	{
		if (arr1[i]==arr2[j])
		{
			cout<<arr1[i]<<ends;
			++i;
			++j;
		}
		else if (arr1[i] < arr2[j])
			++i;
		else ++j;
	}
	cout<<endl;
}

//======================================??????解法有问题
//找出出现基数次的元素  ??若有多个元素出现奇数次??
int findOdd(vector<int> & arr)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	int result = arr[0];
	for (unsigned i=1;i<arr.size();++i)
	{
		result = result^arr[i];
	}
	cout<<"出现奇数次的元素为:"<<result<<endl;
	return result;
}

//求数组中满足给定和的数对
void pairNum(vector<int> & arr1,vector<int> & arr2,int num)
{
	cout<<endl<<"原始数组分别为:"<<endl;
	printArry(arr1);
	printArry(arr2);
	cout<<"满足指定和的数对有: ";
	unsigned i = 0;
	int j = arr2.size()-1;
	while (i<arr1.size() && j>=0)
	{
		if (arr1[i]+arr2[j] == num)
		{
			cout<<arr1[i++]<<","<<arr2[j--]<<ends<<ends;
		}
		else if (arr1[i]+arr2[j] < num)
		{
			++i;
		}
		else --j;
	}
	cout<<endl;
}

//连续最大和   ???如何求出这些连续的位置??
int maxAdd(vector<int> & arr)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	int maxNum= arr[0];
	int pos =0;
	int currSum = 0;
	int currPos = 0;
	for (unsigned i=0;i<arr.size();++i)
	{
		currSum = currSum+arr[i];
		if (currSum>=0)
		{
			/*maxNum = max(maxNum,currSum);*/
			if (currSum > maxNum)
			{
				maxNum = currSum;
				pos = currPos;
			}
		}
		else 
		{
			currSum=0;
			currPos = i;
		}
	}
	cout<<"数组的连续最大和为:"<<maxNum<<endl;
	return maxNum;
}

//数组循环移位   两种方法:1 队列  2交换
void cycleArry(vector<int> & arr)
{

}


//数字组合  回溯
void  Combine1(vector<int> & arr,int temp[],int k,int level)
{
	int begin;
	if (level ==0)
		begin =0;
	else
		begin = temp[level-1]+1;
	int end = arr.size() - k + level;
	for (int i=begin;i<=end;++i)
	{
		temp[level] =  i;
		if (level == k-1)
		{
			for (int j=0;j < k;++j)
			{
				cout<<arr[temp[j]]<<",";
			}
			cout<<ends<<ends;
		}
		else
			Combine1(arr,temp,k,level+1);
	}

}
bool isvalid(int temp[],int level,int num)
{
	for(int i=0;i<level;++i)
	{
		if (temp[i] >= num)
		{
			return false;
		}
	}
	return true;
}

void  Combine(vector<int> & arr,int temp[],int k,int level)
{
// 	int begin;
// 	if (level ==0)
// 		begin =0;
// 	else
// 		begin = temp[level-1]+1;
// 	int end = arr.size() - k + level;
	for (unsigned i=0;i<arr.size();++i)
	{
		if (isvalid(temp,level,i))
		{
			temp[level] =  i;
			if (level == k-1)
			{
				for (int j=0;j < k;++j)
				{
					cout<<arr[temp[j]]<<",";
				}
				cout<<ends<<ends;
			}
			else
				Combine(arr,temp,k,level+1);
		}
	}
}

void DfsCombine(vector<int> & arr,int k)
{
	int * temp = new int[k];
	int level =0;
	Combine1(arr,temp,k,level);
}

//合并两个数组
void CombineVector(vector<int> & arr1,vector<int> & arr2,vector<int> & arr)
{
	cout<<endl<<"原始数组分别为:"<<endl;
	printArry(arr1);
	printArry(arr2);
	arr.resize(arr1.size()+arr2.size());
	unsigned i=0,j=0;
	int k=0;
	while(i<arr1.size() && j < arr2.size())
	{
		if (arr1[i] <= arr2 [j])
			arr[k++] = arr1[i++];
		else
			arr[k++] = arr2[j++];
	}
	while(i<arr1.size()) arr[k++] = arr1[i++];
	while(j<arr2.size()) arr[k++] = arr2[j++];
	cout<<"合并后的数组为:"<<ends;
	printArry(arr);
}


//绝对值最小的元素   //二分法遇到连续相等的情况怎么办?
//通过二分法查找正负数分界点  
void minAbs(vector<int> & arr,int &i,int &j)
{
	if (j-i==1)
	{
		return ;
	}
	int middle = (i+j)/2;
	if (arr[middle] >= 0)
	{
		j = middle;
	}
	else i = middle;
	minAbs(arr,i,j);
}

void minAbs1(vector<int> & arr,int &i,int &j)
{
	while((j-i)!=1)
	{
		int middle = (i+j)/2;
		if (arr[middle] >= 0)
		{
			j = middle;
		}
		else i = middle;
	}
}

int minAbs(vector<int> & arr)
{
	cout<<endl<<"原始数组:";
	printArry(arr);
	if (arr[0]>=0)
	{
		cout<<"绝对值最小的元素是:"<<arr[0]<<endl;
		return arr[0];
	}
		
	if (arr[arr.size()-1]<=0)
	{
		cout<<"绝对值最小的元素是:"<<arr[arr.size()-1]<<endl;
		return arr[arr.size()-1];
	}
	int i=0;
	int j = arr.size()-1;
	minAbs(arr,i,j);
	cout<<"绝对值最小的元素是:"<<min(-arr[i],arr[j])<<endl;
	return min(-arr[i],arr[j]);
}

//二分查找是否含有某元素
bool  binarySearch(vector<int> & arr,int k)
{
	cout<<endl<<"原始数组为:"<<ends;
	printArry(arr);
	int i=0;
	int j= arr.size()-1;
	int flag =0;
	while(i<=j)
	{
		int middle = (i+j)/2;
		if (arr[middle] == k)
		{
			flag =1;
			break;
			//return true;
		}
		else if (arr[middle] < k)
		{
			i = middle+1;
		}
		else j = middle-1;
	}
	cout<<"次数组是否包含数字"<<k<<"? 答:"<<flag<<endl;
	if (flag)
		return true;
	else return false;
}

//将数组重新排序,将数值为0的元素放到最前面,剩下的元素按原始顺序后移
void reSort(vector<int> & arr)
{
	cout<<"原始数组:"<<ends;
	printArry(arr);
	cout<<"重排数组:"<<ends;
	int i= arr.size()-1;
	int j;
	while(1)
	{
		while(i>=0 && arr[i])
			--i;
		if (i < 0)
			break;
		j = i;
		while(j>=0 && !arr[j])
			--j;
		if (j<0)
			break;
		swap(arr[i],arr[j]);
		--i;
	}
	printArry(arr);
}


//字符数组的翻转
void reverseArry(vector<char> & arr)
{
	for (unsigned k=0;k<arr.size();++k)
	{
		cout<<arr[k]<<" ";
	}
	cout<<endl;

	int i=0;
	int j= arr.size()-1;
	while(i<j)
	{
		swap(arr[i++],arr[j--]);
	}

	for (unsigned k=0;k<arr.size();++k)
	{
		cout<<arr[k]<<" ";
	}
	cout<<endl;
}

//语句的翻转
void reverseString(string & str,int fist,int end)
{
	while(fist<end)
	{
		swap(str[fist++],str[end--]);
	}
}

void reverseString(string & str)
{
	cout<<"反转前:"<<str<<endl;
	unsigned i=0,j=0;
	while(j<str.size())
	{
		while(i<str.size() && str[i]==' ')
		{
			++i;
		}
		j = i;
		while(j<str.size() && str[j]!=' ')
			++j;
		reverseString(str,i,j-1);
		i=j;
	}
	reverseString(str,0,str.size()-1);
	cout<<"翻转后:"<<str<<endl;
}

//最长公共子序列
int LCS(vector<int> & arr1,vector<int> & arr2)
{
	unsigned m = arr1.size();
	unsigned n = arr2.size();
	vector<vector<int>> arr;
	arr.resize(m+1);
	for (unsigned i=0;i<m+1;++i)
	{
		arr[i].resize(n+1);
	}
	for (unsigned i=0;i<m+1;++i)
		arr[i][0] =0;
	for(unsigned j=0;j<n+1;++j)
		arr[0][j] = 0;
	for (unsigned i = 1;i< m+1; ++i)
	{
		for (unsigned j = 1;j < n+1; ++j)
		{
			if (arr1[i-1]==arr2[j-1])
			{
				arr[i][j] = arr[i-1][j-1]+1;
			}
			else
				arr[i][j] = max(arr[i-1][j],arr[i][j-1]);
		}
	}
	int result = arr[m][n];
	cout<<"最长公共子序列长度为:"<<arr[m][n]<<endl;
	cout<<"输出其中一个最长的公共子序列:"<<endl;
	//如何使用回溯算法将全部情况输出?
	vector<int> temp;
	temp.resize(result);
	while(m && n)
	{
		if (arr1[m-1]==arr2[n-1])
		{
			temp[--result] = arr1[m-1];
			--m;
			--n;
		}
		else if (arr[m-1][n] > arr[m][n-1])
		{
			--m;
		}
		else
			--n;
	}
	for (unsigned k=0;k<temp.size();++k)
	{
		cout<<temp[k]<<" ";
	}
	cout<<endl;
	return arr[m][n];
}

//最长公共子串
int LCSS(string & str1,string & str2)
{
	//初始化
	unsigned m = str1.size();
	unsigned n = str2.size();
	vector<vector<char>> arr;
	arr.resize(m+1);
	for (unsigned i =0;i<m+1;++i)
		arr[i].resize(n+1);
	for (unsigned i=0;i<m+1;++i)
		arr[i][0] = 0;
	for (unsigned i=0;i<n+1;++i)
		arr[0][i] = 0;
	//填充
	for(unsigned i=1;i<m+1;++i)
	{
		for (unsigned j=1;j<n+1;++j)
		{
			if (str1[i-1]==str2[j-1])
			{
				arr[i][j] = arr[i-1][j-1]+1;
			}
			else arr[i][j] = 0;
		}
	}

	//计算
	int result = 0;
	int pos =0;
	for (unsigned i=1;i<n+1;++i)
	{
		if (result<arr[m][i])
		{
			result = arr[m][i];
			pos = i;
		}
	}
	vector<char> temp;
	temp.resize(result);
	int k = result;
	while(k > 0)
	{
		temp[--k] = str2[--pos];
	}
	cout<<"两个字符串的最长公共子串长度为:"<<result<<endl;
	cout<<"最长公共子串为:";
	for (unsigned i=0;i<temp.size();++i)
	{
		cout<<temp[i];
	}
	cout<<endl;

	return result;
}


//最长递增子序列
//0(n2) 写法
int LIS(vector<int> & arr)
{
	int n = arr.size();
	vector<int> lis;
	lis.resize(n);//存储当前结点最长的递增子序列
	//maxV.resize(n);//当前结点最长的递增子序列的最大值
	for (int i=0;i<n;++i)
	{
		//maxV[i] = 1;
		lis[i]=1;
	}
	//maxV[0] = arr[0];
	for (int i=1;i<n;++i)
	{
		for(int j=0;j<i;++j)
		{
			if (arr[i]>arr[j] && lis[i]<=lis[j])
			{
				lis[i] = lis[j]+1;
			}
		}
	}

	//找最大值
	int maxN = lis[0];
	for (int i=1;i<n;++i)
	{
		if (lis[i]>maxN)
		{
			maxN = lis[i];
		}
	}
	cout<<"最长递增子序列的长度为:"<<maxN<<endl;;
	return maxN;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值