LeetCode Two Sum

来源:互联网 发布:电脑三维绘图软件 编辑:程序博客网 时间:2024/06/05 06:18

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=9

Output: 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 kint[] 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];//构造hashMapMap<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 divideQuery(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;else return 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;}




0 0
原创粉丝点击