您的位置:首页 > 其它

LeetCode Two Sum

2015-05-06 09:52 387 查看
Given an array of integers, find two numbers such that they add up to a specific target number.The function twoSum should return result of the two numbers such that they add up to the target . Please note that your returned answers (both result1 andresult2) are not zero-based.You may assume that each input would have exactly one solution.Input: numbers={2, 7, 11, 15}, target=9Output: result1=2, result2=7一:若数组无序方法一,使用双重循环,遍历数组的方法,确定一个数之后查找数组以确定另外一个数是否也存在数组中
/*2:
* 寻找和为定值的两个数
* 问题描述:给定一个数组和一个数,要求在数组中找出两个数,使其和为该数,并输出这两个数
*
* 方法一:该算法的时间复杂度为o(n*n),双重循环
* 分析:
* 1,给定无序数组T,整数k
* 2,i=0->T.length   int temp=k-T[i]
* 3,j=i+1->T.length 	if(temp==T[j])	return T[I],T[j]
* @param Targent目标无序数组
* @param k和值
* @param 返回值为一个数组,存放结果的两个数
*/
public int[] twoSum1(int[] Targent,int k){
int[] result=new int[2];
int temp=0;
for(int i=0;i<Targent.length;i++){
temp=k-Targent[i];				//第一个数确定的情况下,求出第二个数
for(int j=1+i;j<Targent.length;j++){
if(temp==Targent[j]){		//在数组中寻找第二个数是否存在,若存在,则返回两个数
result[0]=Targent[i];
result[1]=Targent[j];
return result;
}
}
}
return result;
}
方法二,使用hashmap映射的方法
/*
* 方法四:利用hashMap存放互补数组,将原数组和互补数组作映射,查找hashMap的时间复杂度为O(1),与处理hashMap的时间
* 复杂度为O(n),故该方法的时间复杂度为O(n),但是需要O(N)的hashMap空间复杂度,在时间复杂度要求比较高的情况下,可以利用
* 空间换时间!
* 伪代码:
* 1,int[] T,int k		int[] R=k-T[i] i=0->T.length
* 2,hashMap.put(k-T[i],T[i])   i=0->T.length-1		//构造hashMap,key=k-T[i],value=T[i] ,时间复杂度为O(n)
* 3,if(hashMap.containsKey(T[i]))	return T[i],k-T[i];		//containsKey(key)根据hashMap中是否存在键值,来返回
* @param Targent为无序或者有序数组
* @param k为输入和值
* @param 返回值为二维数组
*/
public int[] twoSum4(int[] Targent,int k){
int[] result=new int[2];
//构造hashMap
Map<Integer, Integer> reflectMap=new HashMap();
for(int i=0;i<Targent.length;i++){
//将数组R作为key值,T作为value,时间复杂度为O(n)
reflectMap.put(k-Targent[i], Targent[i]);
}
//根据T[i]查询hashMap,hashMap查询时间复杂度为O(1)
for(int i=0;i<Targent.length;i++){
if(reflectMap.containsKey(Targent[i])){
result[0]=Targent[i];
result[1]=k-Targent[i];
return result;
}
}
return result;
}
二:若数组按照升序排列方法一,在循环遍历的基础上使用二分查找,确定一个数之后,使用二分查找另外一个数是否存在于数组之中
/** 算法优化:二分查找的时间复杂度为O(lgn),最坏情况下需要查找n次,故该算法的时间复杂度为O(nlgn)* 					若数组无序,则用快速排序方法进行排序,时间复杂度为O(nlgn),最后总共的时间复杂度为O(nlgn)+O(nlgn)=O(nlgn)* 分析:* 1,int i=0->T.length  int temp=k-T[i]* 2,使用二分查找的方法来寻找temp数值是否在T数组中* @param Targent为有序数组* @param k为输入和值* @param 返回值为二维数组*/public int[] twoSum2(int[] Targent,int k){int[] result=new int[2];int temp=0;for(int i=0;i<Targent.length;i++){			//时间复杂度O(n)temp=k-Targent[i];if(divideQuery(Targent, temp)){			//时间复杂度O(lgn)result[0]=Targent[i];result[1]=temp;return result;}}return result;}/** 二分查找:递归实现,时间复杂度为O(lgn)* 分析:* 1,对于一个有序数组T,所需要查找的数为k* 2,int index = (T.length-1)/2		//找到数组中位数的下标指针* 3,boolean divideQuery'(int[] Targent, int k, int left, int right)* 				if(k<T[index])	return divideQuery(T, k , 0 ,index-1)* 				else if(k==T[index])		return true* 				else 	return divide	Query(T,  k, index+1, T.length-1)* 4,if(left==index&&Targent[index]!=k)	return false;	//递归结束判断* @param Targent目标有序数组* @param k需要查找的数* @param 返回值为boolean ,存在k则返回true ,否则返回false*/public  boolean divideQuery(int[] Targent,int k) {int firstIndex=Targent.length-1;if(k<Targent[0]||k>Targent[firstIndex])return false;return divideQuery(Targent, k,	0 , firstIndex);}private  boolean divideQuery(int[] Targent, int k ,int left ,int right) {int index=(right+left)>>1;//该判断为递归结束的判断条件,否则递归不能结束if(left==index&&Targent[index]!=k)return false;if(k<Targent[index])return divideQuery(Targent, k, left, index-1);else if(k==Targent[index])return true;elsereturn divideQuery(Targent, k, index+1, Targent.length-1);}/** 二分查找:while循环实现,对于有序数组时间复杂度为O(lgn)* 伪代码:* 1,int left=0,right=T.length-1* 2,int index=(left+right)>>1* 3,while(left!=right){* 			if(T[index]>k){			//若中位数比k大,则说明k在中卫数之前,需要将right指针左移一位* 				right=index-1;* 				index=(left+right)>>1;}* 			else if(T[index]==k)	//若中位数与k相等,则返回找到* 				return true* 			else{							//若中位数比k小,则说明k在中位数后面,需要将left指针加一* 				left=index+1* 				index=(left+right)>>1}* 			}* @param Targent目标有序数组*/public boolean divideQuery2(int[] Targent,int k){int left=0;int right=Targent.length-1;int index=(right+left)>>1;//此处找到循环条件需要注意left<=right为正确,不能选择left!=right否则//当查找到left==right时,循环结束,该条件下没有判断while(left<=right){if(Targent[index]>k){//注意找到中位数之后,right指针需要变动right=index-1;index=(left+right)>>1;}else if(Targent[index]==k)return true;else{//注意找到中位数之后,left指针需要变动left=index+1;index=(left+right)>>1;}}return false;}
方法二,可以使用求互补数组的方法,对于升序排列的数组,求出其互补数组,若存在两个数相加等于目标数,则在这两个数组之中一定存在相等的两个数。
/** 求互补数组的方法* 算法时间复杂度为O(n),但是需要求出互补数组,故空间复杂度为O(n)* 1,若有序数组T中存在两个数a,b 使得a+b=k成立* 2,作数组D=k-T[i],则a,b两数一定在数组D中存在* 3,定义两个整形变量i,j,使i从T数组左边开始遍历,j从D数组右边开始遍历,若找到相等的数,则返回找到,一直到i=j* 例如,若数组T={1,2,4,7,11,15},若k=15,则数组D={14,13,11,8,4,0},4+11=15成立,故若4在数组T中,则在D中也一定存在* 伪代码:* 1,int T,* 2,int D=k-T[i]	i=0->T.length;* 3,while(i!=j)* 			if(T[i]>D[J])* 				J++;* 			if(T[i]==D[j])* 				return T[i],k-T[i]* 			if(T[i]<D[j])* 				i++* 		return -1* @param Targent为无序或者有序数组* @param k为输入和值* @param 返回值为二维数组*/public int[] twoSum3(int[] Targent,int k){int[] result=new int[2];//计算数组T的差分数组,时间复杂度为O(n)int[] minus=new int[Targent.length];for(int i=0;i<Targent.length;i++){minus[i]=k-Targent[i];}//定义两个指针int i=0;int j=Targent.length-1;while(i!=j){			//时间复杂度为O(n),遍历指针i+j<=nif(Targent[i]==minus[j]){result[0]=Targent[i];result[1]=k-Targent[i];return result;}if(Targent[i]>minus[j])j--;if(Targent[i]<minus[j])i++;}return result;}
方法三,该算法在升序排列的基础上,为最好的算法。
/** 最好的算法,* 要求数组为有序数组,此时时间复杂度为O(n),否则先进行排序,时间复杂度为O(NLGN)+O(N)* 寻找时间复杂度为O(N),空间复杂度为O(1)的算法* 分析:* 1,对于数组T,若数组无序,则首先对数组进行排序,时间复杂度为O(nlgn)* 2,定义两个指针,left=0,right=T.length-1分别从数组的两端遍历数组* 3,若T[left]+T[right]>K,则使right指针左移一位,减小两个数的和值* 4,若T[left]+T[right]<K,则使left指针右移一位,增加两个数的和值* 5,当指针left=right时,结束循环判断* @param Targent为有序数组* @param k为输入的数* @param 返回值为一个二维数组*/public int[] twoSum5(int[] Targent,int k){//定义存放结果的数组int[] result=new int[2];//定义两个指针int left=0;int right=Targent.length-1;//循环控制,判断T[left]+T[right]与K值的大小while(left<right){if(Targent[left]+Targent[right]>k)right--;else if(Targent[left]+Targent[right]<k)left++;else {result[0]=Targent[left];result[1]=Targent[right];return result;}}return result;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: