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;
例如,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;
}
}