内容六
思路:像这种一对一对的东西首先想到了合并排序,因为合并排序合并的过程就遍历了所有的数对。现在只要判断是否存在一个和为S的数对就行。
分成子问题后,有序了,可以用二分搜索查找。
import java.util.Arrays;
import java.util.Scanner;
/**
* @author SJ
* @date 2020/10/15
*/
public class HasSum {
public HasSum(int length) {
temp=new Integer[length];
}
public static Integer[] temp ;
public static boolean merge(int[] nums, int left, int right, int sum) {
for (int i = left; i <= right; i++) {
temp[i] = nums[i];
}
int middle = (left + right) / 2;
int l = left;
int r = middle + 1;
for (int i = left; i <= right; i++) {
//左边合并完成,右边还有剩余
if (l == middle + 1 && r < right + 1)
nums[i] = temp[r++];
//右边合并完成,左边还有剩余
else if (r == right + 1 && l < middle + 1)
nums[i] = temp[l++];
else if (temp[l] <= temp[r]) {
nums[i] = temp[l++];
//用二分搜索
int index = Arrays.binarySearch(temp, r, right, sum - nums[i]);
if (index >= 0) {
// System.out.println(nums[i] + "," + temp[index]);
return true;
}
} else {
nums[i] = temp[r++];
int index = Arrays.binarySearch(temp, l, middle, sum - nums[i]);
if (index >= 0) {
// System.out.println(nums[i] + "," + temp[index]);
return true;
}
}
}
return false;
}
public static boolean mergeSort(int[] nums, int left, int right, int sum) {
boolean leftCount = false;
boolean rightCount = false;
boolean mix = false;
if (left == right)
return false;
else if (left < right) {
leftCount = mergeSort(nums, left, (left + right) / 2, sum);
rightCount = mergeSort(nums, (left + right) / 2 + 1, right, sum);
mix = merge(nums, left, right, sum);
}
return leftCount || rightCount || mix;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int length = scanner.nextInt();
new HasSum(length);
int[] nums = new int[length];
// int[] nums={3,5,7,2,1};
int sum = scanner.nextInt();
for (int i = 0; i < length; i++) {
nums[i] = scanner.nextInt();
}
boolean b = mergeSort(nums, 0, nums.length - 1, sum);
if (b)
System.out.println("YES");
else
System.out.println("NO");
}
}
结果:
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"...
5 7
3 6 7 2 1
YES
Process finished with exit code 0
时间复杂度 空间O(n)