面试中很多题目都是给定一个数组,要求返还两个下标的。高效解法:先排序,然后在一个循环体里利用两个变量进行反向的遍历,并且这两个变量遍历的方向是不变的,从而保证遍历算法的时间复杂度。
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Test;
import java.util.ArrayList;
import java.util.List;
/**
*
* 2.12 快速寻找满足条件的两个数
*/
public class SearchArrySum {
private static List<Integer> result = new ArrayList();
private static int num = 3;
private static int sum = 16;
public static void main(String[] args) {
int[] arry = new int[]{4,16 , 1, 9, 13, 10, 8};
//解法三
int[] num3 = searchsum(arry, sum);
System.out.println("满足的两个值:" + num3[0] + "," + num3[1]);
//扩展问题1.1 三个值的和符合条件
int[] num11 = searchsumthree1(arry, sum, 3);
System.out.println("满足的三个值:" + num11[0] + "," + num11[1] + "," + num11[2]);
//扩展问题1.2 任意个值的和符合条件
List<Integer> num12 = searchsumN(arry, sum, num);
if (num12.size() == num) {
for (int i : num12) {
System.out.print(i + ",");
}
} else {
System.out.print("无法满足条件");
}
System.out.println();
//扩展问题2 如果完全相等的一对数字找不到,能否找出和最接近的解
int[] num21 = searchsumclosed(arry, sum);
System.out.println("最接近的数字:" + num21[0] + "," + num21[1]);
}
private static int[] searchsum(int[] arry, int sum) {
int[] r_arry = new int[2];
quick_sort(arry, 0, arry.length - 1);
for (int i = 0, j = arry.length - 1; i < j;) {
if (arry[i] + arry[j] == sum) {
r_arry[0] = arry[i];
r_arry[1] = arry[j];
return r_arry;
} else if (arry[i] + arry[j] < sum) {
i++;
} else {
j--;
}
}
return r_arry;
}
private static int[] searchsumthree1(int[] arry, int sum, int n) {
int[] r_arry = new int[n];
quick_sort(arry, 0, arry.length - 1);
for (int i = 0, j = arry.length - 1; i < j - 1;) {
for (int l = i + 1; l < j;) {
if (arry[i] + arry[l] + arry[j] == sum) {
r_arry[0] = arry[i];
r_arry[1] = arry[l];
r_arry[2] = arry[j];
return r_arry;
} else if (arry[i] + arry[l] + arry[j] < sum) {
l++;
} else {
j--;
}
}
i++;
}
return r_arry;
}
private static List searchsumN(int[] arry, int sum, int n) {
quick_sort(arry, 0, arry.length - 1);
if (n == 2) {
for (int i = 0, j = arry.length - 1; i < j;) {
if (arry[i] + arry[j] == sum) {
result.add(arry[i]);
result.add(arry[j]);
return result;
} else if (arry[i] + arry[j] < sum) {
i++;
} else {
j--;
}
}
return result;
} else {
for (int i = 0; i < arry.length; i++) {
int tmp = arry[i];
int[] arry_tmp = copyarry(arry, i);
int sum_tmp = sum - tmp;
result.add(tmp);
result = searchsumN(arry_tmp, sum_tmp, n - 1);
if (result.size() == num) {
return result;
} else {
result.remove(result.size() - 1);
}
}
return result;
}
}
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;
}
private static int[] searchsumclosed(int[] arry, int sum) {
int[] r_arry = new int[2];
int[] min_arry = new int[2];
int[] max_arry = new int[2];
int min_tmp = 0;
int max_tmp = 0;
quick_sort(arry, 0, arry.length - 1);
for (int i = 0, j = arry.length - 1; i < j;) {
int tmp = arry[i] + arry[j];
if (tmp == sum) {
r_arry[0] = arry[i];
r_arry[1] = arry[j];
return r_arry;
} else if (tmp < sum) {
if (tmp > min_tmp) {
min_tmp = tmp;
min_arry[0] = arry[i];
min_arry[1] = arry[j];
}
i++;
} else {
if (tmp < max_tmp || max_tmp == 0) {//假设max_tmp的值一定不等于0,如果max_tmp的值可能等于0,这样就有问题
max_tmp = tmp;
max_arry[0] = arry[i];
max_arry[1] = arry[j];
}
j--;
}
}
if (r_arry[0] == 0 && r_arry[1] == 0) {
//比较min_tmp、max_tmp哪个值更接近sum
if (min_tmp != 0 && max_tmp != 0) {
int min = sum - min_tmp;
int max = max_tmp - sum;
if (min < max) {
r_arry[0] = min_arry[0];
r_arry[1] = min_arry[1];
} else {
r_arry[0] = max_arry[0];
r_arry[1] = max_arry[1];
}
} else if (min_tmp == 0) {
r_arry[0] = max_arry[0];
r_arry[1] = max_arry[1];
} else if (max_tmp == 0) {
r_arry[0] = min_arry[0];
r_arry[1] = min_arry[1];
}
}
return r_arry;
}
//快速排序
static void quick_sort(int s[], int l, int r) {
if (l < r) {
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int i = l, j = r, x = s[l];
while (i < j) {
while (i < j && s[j] >= x) // 从右向左找第一个小于x的数
{
j--;
}
if (i < j) {
s[i++] = s[j];
}
while (i < j && s[i] < x) // 从左向右找第一个大于等于x的数
{
i++;
}
if (i < j) {
s[j--] = s[i];
}
}
s[i] = x;
quick_sort(s, l, i - 1); // 递归调用
quick_sort(s, i + 1, r);
}
}
}