查找

9.给定n个元素构成的数组,找出这个数组中和为0的元素组合。要求不能有重复的组合。
例如,array={-1,0,1,2,-1,-4},满足题意的组合是(-1,0,1)和(-1,-1,2)
solution:
如果使用暴力查找的算法,也就是先选出第一个元素,然后选出第二个和第三个,那么算法的时间复杂度为O(n*n*n)
可以先对数组进行排序,然后遍历的方式选出第一个元素,再通过两指针的方式找出第二和第三个的元素。两指针的
使用和题1完全相同。由于遍历第一个元素的时间复杂度O(n),两个指针查找第二和第三个元素的时间复杂度是O(n),
排序的时间复杂度是O(nlogn),所以这个算法的时间复杂度T(n)=O(n*n)+O(nlogn)=O(n*n)
具体算法的代码实现如下:

import java.util.ArrayList;
import java.util.Arrays;

public class question9 {

    ArrayList<ArrayList<Integer>> get3SumResultSet(int[] array) {
        ArrayList<ArrayList<Integer>> resultSet = new ArrayList<ArrayList<Integer>>();
        if (array == null || array.length < 3)
            return resultSet;
        else {
            Arrays.sort(array);// 先对给定数组进行排序
            for (int i = 0; i < array.length - 2; i++) {
                if (array[i] > 0)// 由于数组是有序的,第一个元素如果大于0,那么这时候没有满足条件的元素组合,退出查找
                    break;
                else {
                    if (i > 0 && array[i] == array[i - 1])//题目要求合并相同的元素组合,所以需要过滤重复的元素
                        continue;//这句是过滤重复的第1个元素,后面会看到过滤第2和第3个元素
                    else {
                        int left = i + 1, right = array.length - 1;//在固定第一个元素为array[i]的情况下,使用两指针查找
                        while (left < right) {
                            if (array[i] + array[left] + array[right] < 0)//三个元素的和小于0,左边的指针右移
                                left++;
                            else if (array[i] + array[left] + array[right] > 0)//三个元素的和大于0,右边的指针左移
                                right--;
                            else {
                                ArrayList<Integer> result = new ArrayList<Integer>(
                                        3);//当三个元素的和恰好等于0的时候,new一个长度为3的数组,用来存放符合题意的结果
                                result.add(array[i]);//分别记录符合条件的array[i],array[left],array[right]
                                result.add(array[left]);
                                result.add(array[right]);
                                
                                resultSet.add(result);//将符合条件的三个元素加入到resultSet中

                                do {//过滤相同的第2个元素
                                    left++;
                                } while (left < right
                                        && array[left] == array[left - 1]);
                                do {//过滤相同的第3个元素
                                    right--;
                                } while (left < right
                                        && array[right] == array[right + 1]);
                            }
                        }
                    }
                }
            }
        }
        return resultSet;
    }
}

10. 给定数组,和一个目标值target。需要找出数组中和等于target的三个元素的全部组合,输出是不能有重复的元素组合
例如,array={-1,2,1,-4},target=1,输出是(-1,2,1)
solution:
解决的算法和题9完全相同,只是在方法的参数上添加一个target变量。在判断的时候将第9题的0改成target。实现的代码如下:
import java.util.ArrayList;
import java.util.Arrays;

public class question10 {
    ArrayList<ArrayList<Integer>> get3SumResultSet(int[] array, int target) {
        ArrayList<ArrayList<Integer>> resultSet = new ArrayList<ArrayList<Integer>>();
        if (array == null || array.length < 3)
            return resultSet;
        else {
            Arrays.sort(array);// 先对给定数组进行排序
            for (int i = 0; i < array.length - 2; i++) {
                if (array[i] > target)// 由于数组是有序的,第一个元素如果大于target,后面的元素一定大于target,那么这时候没有满足条件的元素组合,退出查找
                    break;
                else {
                    if (i > 0 && array[i] == array[i - 1])// 题目要求合并相同的元素组合,所以需要过滤重复的元素
                        continue;// 这句是过滤重复的第1个元素,后面会看到过滤第2和第3个元素
                    else {
                        int left = i + 1, right = array.length - 1;// 在固定第一个元素为array[i]的情况下,使用两指针查找
                        while (left < right) {
                            if (array[i] + array[left] + array[right] < target)// 三个元素的和小于target,左边的指针右移
                                left++;
                            else if (array[i] + array[left] + array[right] > target)// 三个元素的和大于target,右边的指针左移
                                right--;
                            else {
                                ArrayList<Integer> result = new ArrayList<Integer>(
                                        3);// 当三个元素的和恰好等于target的时候,new一个长度为3的数组,用来存放符合题意的结果
                                result.add(array[i]);// 分别记录符合条件的array[i],array[left],array[right]
                                result.add(array[left]);
                                result.add(array[right]);

                                resultSet.add(result);// 将符合条件的三个元素加入到resultSet中

                                do {// 过滤重复的第2个元素
                                    left++;
                                } while (left < right
                                        && array[left] == array[left - 1]);
                                do {// 过滤重复的第3个元素
                                    right--;
                                } while (left < right
                                        && array[right] == array[right + 1]);
                            }
                        }
                    }
                }
            }
        }
        return resultSet;

    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值