#include <iostream> #include <cmath> #include <climits> using namespace std; void FindClosestPair(int *a,int n,int sum) { int i=0,j=n-1; int dif=INT_MAX; int Start=0,End=0; //存储输出的元素 while(i<n&&j>i) { if(abs(a[i]+a[j]-sum)<dif) { Start=a[i]; End=a[j]; dif=abs(a[i]+a[j]-sum); } else if(a[i]+a[j]<sum) { //若当前差值依然是最小的,并且两数之和比期望值小, //说明应该增大左边的值 i++; } else { j--; } } cout<<Start<<" "<<End<<endl; } int main() { int a[]={-5,-1,0,1,4,5,7,9}; FindClosestPair(a,8,8); return 0; }
head在什么情况下可能移动到i的右边?假设head已经移动到了i的右边,即head > i且numbers [head] > numbers [i] ,根据算法规则,只有当numbers [head] + numbers [tail] < target时,head才会右移,所以 numbers [tail] < target - numbers [head] < target - numbers [i] = numbers [j] ,意味着tail一定出现在j的左边。
那tail在什么情况下可能移动到j的左边?同理,只有当head在i的右边时才可能发生。
因为一开始head在i的左边,tail在j的右边,算法每次只移动head或tail,所以不可能出现某一时刻经过算法移动后,head移动到i的右边而同时tail移动到j的左边的情况。证明结束。
public void minDiff(int[] nums, int sum) { int low = 0; int high = nums.length - 1; int diff = Integer.MAX_VALUE; int a = 0; int b = 0; while (low < high) { if (Math.abs(nums[low] + nums[high] - sum) < diff) { diff = Math.abs(nums[low] + nums[high] - sum); a = nums[low]; b = nums[high]; } else if (nums[low] + nums[high] > sum) { high --; } else { low ++; } } System.out.printf("a,b is %d, %d", a, b); }
public class ABSum { public static void main(String[] args) { int[] nums = {-5, -1, 0, 1, 4, 5, 7, 9}; getAB(nums, 6); int[] nums2 = {1, 3, 4, 5, 6, 7, 8, 9}; getAB(nums2, 4); } public static void getAB(int[] nums, int sum) { int left = 0, right = nums.length - 1; int dif = Integer.MAX_VALUE; while(left < nums.length - 1 && left < right) { if(dif > Math.abs(nums[left] + nums[right] - sum)) { dif = Math.abs(nums[left] + nums[right] - sum); } if(dif == 0) { break; } if(nums[left] + nums[right] > sum) { right--; }else { left++; } } System.out.println(nums[left] + " " + nums[right]); } }