亲爱的大神老爷们,这是小渣第一次写blog,欢迎大家来喷(批评指正),算法渣因为面试中连这道题都不会写就自己琢磨了一下,也参考了网上大家的做法
解法一:
思路:从首尾向目的靠拢,因为已经排序,【假设存在A[i]+A[j]=x】 (i<j:这样的i,j对可能不止一对,只要确保如果存在这样的i,j对,设计的算法一定能找到其中一对算法就算有效,该算法找到的是【最小i和最大j】那一对,那么在查找过程中始终有:【A[head]<=A[i]&&A[j]<=A[tail]】):
在靠拢的过程中head从0开始增加,tail从A.length-1开始减小,若A[head]+A[tail]>x,必然有tail>j,所以要做的就是减小tail,同理,在和小于x时,必有head<i,增大head即可
代码:如果乱序输入,自己写个排序就好
# include <iostream.h> # include "IO_tools.cpp" void main(){ int A[6]; inputA(A,6); outputA(A,6); int x; int i,j,sum=0; while(true){ cout<<"Input x:"; cin>>x; i=0;j=5; while(i<j){ sum=A[i]+A[j]; if(sum==x){ cout<<"x="<<A[i]<<"+"<<A[j]<<endl; break; } else if(sum<x) i++; else j--; } } }
解法2:考察A[i](i from 0 to A.length):如果存在A[j]=x-A[i]【i!=j】,结束,找到;如果遍历完数组未找到这样的一对元素,结束
进一步细化:对A排序后,如果A[i]<x-A[i],则在i之后找x-A[i]就好,否则在i之前找。
错误分析:之前并未对查找的区间做限制,那么如果并不存在这样的两个元素,而恰好2*A[i]=x,则会误把A[i]当成两个元素使用,从而导致该算法并不正确。
# include <iostream.h> # include "IO_tools.cpp" # include "Merge_sort.cpp" # include "binary_search.cpp" void main(){ int A[10],i=10,find; //初始化 inputA(A,10); outputA(A,10); //归并排序 Merge_sort(A,0,9); //输出结果 cout<<"After Sorted:"; outputA(A,10); while(true){ int x; cout<<"Input x:"; cin>>x; i=10; find=0; //按目的数与当前数的大小关系确定目的数所在区间(如果目的数存在);错误避免:A[i]+A[i]=x时不会误把一个数当两个数用;效率提升:不要在整个数组内查找; while(i--){ //二分查找:前提是已经排序 int aim=x-A[10-i-1]; int result=aim<A[10-i-1] ? binary_search(A,aim,0,10-i-2) : binary_search(A,aim,10-i,9);//result为目的数数组下标(-1代表目的数不存在) if(result>=0){ cout<<"Find it:"<<A[10-i-1]<<"+"<<aim<<"="<<x<<endl; find++; continue;//找到所有结果 } } if(find==0){ cout<<"Not Found!"<<endl; } } }
时间: 2024-10-05 05:07:36