之前遇到的一道算法题,这里记录一下。
算法思想:因为是有序的,所以我们用s存放第一个元素的下标,用e存放最后一个元素的下标,那么arr[s] 就是所有元素中最小的,arr[e]就是所有元素中最大的,所以我们判断arr[s] + arr[e] - sum的值是否大于0,如果大于0那就说明 arr[e] 太大了,那么就e--。如果小于0,arr[s] 太小了,那就s++。这个时候判断是否距离比上一个我们记录的距离更小,更小的话就更新,距离是|arr[s] + arr[e] - sum|这么算出来的。
因为没在oj或者LeetCode上找到,因此我也不确定代码有没有特殊值遗漏,不过大致思想是这样子的。程序能满足题目的要求
代码如下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[10000];
int n,sum;
scanf("%d %d",&n,&sum);
for(int i=0;i<n;i++) {
scanf("%d",&arr[i]);
}
int s=0,e=n-1;
int dis = abs(arr[n-1] + arr[0] - sum);
int result = dis;
int resa,resb;
int flag = 0;
while(s<e){
dis = arr[s] + arr[e] - sum;
if(dis>0){
if(abs(dis)<result) {
result = abs(dis);
resa = arr[s];
resb = arr[e];
}
e--;
}else if(dis<0){
if(abs(dis)<result) {
result = abs(dis);
resa = arr[s];
resb = arr[e];
}
s++;
}else {
printf("%d %d",arr[s],arr[e]);
flag = 1;
break;
}
}
if(flag==0) {
printf("%d %d",resa,resb);
}
return 0;
}
因为是从头和尾同时开始往中间走,他俩汇合即得到答案,故时间复杂度为O(n)。