java 二元组,笔试面试算法经典--打印数组中相加和为给定值的二元组及三元组(Java)...

【题目】给定一个递增的数组,要求打印数组中和为给定值的二元组,例如: arr[]={-8, -4, -1, 0, 1, 3, 4, 5, 6, 7, 9} , k=10,打印结果为:

1——9

3——7

4——6

1.打印二元组

解法1(时间复杂度 O(N * N)空间复杂度 O(1))

思路:利用双重循环遍历数组中的所有二元组,如果二元组相加的值为 k 打印。

public static void twoTuples1(int arr[],int k)

{

//双重循环遍历每一对双元组

if(arr==null||arr.length==0)

return;

for(int i=0;i

for(int j=i+1;j

{ //如果二元组相加的值为 k则打印

if(arr[i]+arr[j]==k)

System.out.println(arr[i]+" "+arr[j]);

}

}

解法2(时间复杂度 O(N)空间复杂度 O(1))

思路:优化解法1,利用递增数组的性质,使用两个指针 left ,right 分别指向数组的头和结尾,1.如果 arr[left]+arr[right]==k,则打印,然后left++,right–,因为数组 left—right 之间可能还有满足条件的,2.如果arr[left]+arr[right]k, right--。

例如上面数组: arr[]={-8, -4, -1, 0, 1, 3, 4, 5, 6, 7, 9} , k=10, 开始时left指向-8,right指向9,-8+9=1 小于10,那么left++,指向 -4,-4+9=5小于10,依次到left指向1此时 1+9=10,此时left++指向3,right–指向7,3+7=10符合条件。

public static void twoTuples(int arr[],int k)

{

if(arr==null||arr.length==0)

return;

int left=0,right=arr.length-1;

while(left

{

if(arr[left]+arr[right]==k)

{

System.out.println(arr[left]+" "+arr[right]);

left++;

right--;

//arr[left]+arr[right]==k,在left 和 right 之间找符合条件的

}

else if(arr[left]+arr[right]

left++;

//如果 arr[left]+arr[right]

}

else {

right--;

}

}

}

解法3(时间复杂度 O(N)空间复杂度 O(N))

思路:解法2中利用了递增数组的性质,如果数组不递增的话,解法2就不能用了。解法3使用一个hashmap将前面遍历过的值保存起来,后面遍历到arr[j]时到hashmap中找 有没有 值为k-arr[j]的元素,如果有则打印,因为在hashmap中根据key查找只需要O(1)的时间所以算法的时间复杂度为O(N)。用hashmap还有一个好处就是可以去掉重复的二元组。

public static void twoTuples2(int arr[],int k)

{

//使用hashmap进行保存

if(arr==null||arr.length==0)

return;

HashMap hashMap=new HashMap();

for(int i=0;i

{

//如果hashmap中存在k-arr[i],的值则打印

if(hashMap.containsKey(k-arr[i]))

{

System.out.println(k-arr[i]+" "+arr[i]);

}

//如果hashmap中没有存放arr[i],则将arr[i]的值放入到hashmap中。

if(!hashMap.containsKey(arr[i]))

{

hashMap.put(arr[i],i);

}

}

}

2.打印三元组

解法1(时间复杂度O(N * N * N)空间复杂度 O(1))

思路:跟上面的二元组解法1的思路类似,使用三重循环,遍历数组的每一个三元组,如果其和为给定值,则将其打印。

public static void threeTuples(int arr[],int sum)

{

//最简单的方法,使用三重循环遍历所有的三元组。

if(arr==null||arr.length<3)

return;

for(int i=0;i

for(int j=i+1;j

for(int k=j+1;k

{

if(arr[i]+arr[j]+arr[k]==sum)

System.out.println(arr[i]+" "+arr[j]+" "+arr[k]);

}

}

解法2(时间复杂度O(N * N * N)空间复杂度 O(1))

思路:解法1 显然不是一个好方法,利用递增数组的性质,类似于二元组的解法2,三元组只用两重循环就能求解,第一重循环用于选择第一个元素,第二重循环子区间中使用二元组的解法2来做,例如arr[i]+arr[j]+arr[k]=sum,只需要在可以转化为求:arr[j]+arr[k]=sum-arr[i],只要在第一重循环中获得arr[i],后面的:arr[j]+arr[k]=sum-arr[i],就是求二元组问题。

public static void threeTuples2(int arr[],int sum)

{

//双重循环

if(arr==null||arr.length<3)

return;

for(int i=0;i

{

int left=i+1,right=arr.length-1;

while(left

{

if(arr[i]+arr[left]+arr[right]==sum)

{

System.out.println(arr[i]+" "+arr[left]+" "+arr[right]);

left++;

right--;

}

else if(arr[i]+arr[left]+arr[right]

{

left++;

}

else {

right--;

}

}

}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值