//题目:给一个数组,求数组中两个数字之和等于给定数字的元素
//解法1:穷举法,计算两两元素的和是否满足要求,时间复杂度O(n^2)
public class Main {
public static void main(String[] args) {
findNum(new int[]{5,6,8,3,7,9,4},12);
}
public static void findNum(int[] input, int target) {
for(int i = 0;i<input.length;i++){
for(int j = i+1;j<input.length;j++){
if(input[i]+input[j] == target){
System.out.println(input[i]+" "+input[j]);
}
}
}
}
}
//解法2:先排序,再使数组第一个元素与最后一个元素求和,根据sum与target关系调整low和high的位置,时间复杂度O(NlogN)因为要排序
public class Main {
public static void main(String[] args) {
findNum(new int[]{5,6,8,3,7,9,4},12);
}
public static void findNum(int[] input, int target) {
sort(input,0,input.length-1);
int low = 0;
int high = input.length-1;
while(low<high){
int sum = input[low]+input[high];
if(sum == target){
System.out.println(input[low]+" "+input[high]);
high--;
}else if(sum>target){
high--;
}else{
low++;
}
}
}
public static void sort(int[] input, int low, int high){
if(low<high){
int mid = partition(input, low, high);
sort(input, low, mid-1);
sort(input, mid+1, high);
}
}
public static int partition(int[] input, int low, int high){
int temp = input[low];
while(low<high){
while(low<high && input[high]>temp){
high--;
}
input[low] = input[high];
while(low<high && input[low]<temp){
low++;
}
input[high] = input[low];
}
input[low] = temp;
return low;
}
}
//解法3:hash表,以空间换时间,时间复杂度O(N),空间复杂度O(N)
public class Main {
public static void main(String[] args) {
findNum(new int[]{5,6,8,3,7,9,4},12);
}
public static void findNum(int[] input, int target) {
HashSet<Integer> hash = new HashSet<Integer>();
HashSet<Integer> hash1 = new HashSet<Integer>(); //避免重复,3+9 = 12,9+3 = 12
for(int i = 0;i<input.length;i++){
if(!hash.contains(input[i])){
hash.add(input[i]);
}
}
for(int i = 0;i<input.length;i++){
int value = target-input[i];
hash.remove(input[i]); //防止6+6 = 12这种情况发生
if(!hash1.contains(value) && hash.contains(value)){
System.out.println(input[i]+" "+value);
}
hash.add(input[i]);
hash1.add(input[i]);
}
}
}
// 扩展题目:给一个数组,求其中n个数字和为指定数字的n个元素
// 解法:按照循环的方式找前n-2个元素,最后两个元素用之前的方法找
public class Main {
public static void main(String[] args) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> temp = new ArrayList<Integer>();
findNum(new int[]{1,2,3,4,5,6,7,8,9},20,4,temp,result);
for(int i = 0;i<result.size();i++){
printList(result.get(i));
}
}
public static void findNum(int[] input, int target, int n, List<Integer> temp,List<List<Integer>> result) {
if(n == 2){
int low = 0;
int high = input.length-1;
while(low<high){
if(target == input[low]+input[high]){
temp.add(input[low]);
temp.add(input[high]);
if(!isContain(result,temp)){
result.add(new ArrayList<Integer>(temp));
}
return;
}else if(target > input[low]+input[high]){
low++;
}else{
high--;
}
}
return;
}else{
for(int i = 0;i<input.length;i++){
temp.add(input[i]);
int[] input_temp = copyarry(input,i);
findNum(input_temp,target-input[i],n-1,temp,result);
if(temp.size() == 4){
temp.remove(temp.size()-1);
temp.remove(temp.size()-1);
temp.remove(temp.size()-1);
}else{
temp.remove(temp.size()-1);
}
}
}
}
private static int[] copyarry(int[] arry, int i) { //在数组中删除出现过的元素
int[] tmp = new int[arry.length - 1];
int idx = 0;
for (int j = 0; j < arry.length; j++) {
if (j != i) {
tmp[idx++] = arry[j];
}
}
return tmp;
}
public static void printList(List<Integer> list){ //打印列表中元素
for(int i = 0;i<list.size();i++){
System.out.print(list.get(i)+" ");
}
System.out.println();
}
public static boolean isContain(List<List<Integer>> result, List<Integer> temp){ //判断result中是否有与temp一样的组合出现
for(int i = 0;i<result.size();i++){
List<Integer> t = new ArrayList<Integer>();
for(int j = 0;j<result.get(i).size();j++){
t.add(result.get(i).get(j));
}
for(int j = 0;j<temp.size();j++){
if(t.contains(temp.get(j))){
t.remove(temp.get(j));
}
}
if(t.size() == 0){
return true;
}
}
return false;
}
}