算法分析:有序的数组(假设非降序),采取双向遍历,一个从前往后,一个从后往前,当前数字相加如果相等则返回,如果小于k则前面的继续往后,如果大于k则后面的继续往前
代码如下:
typedef struct Pairs
{
int x;//第一个数的下标
int y;//第二个数的下标
}Pairs;
//求一个有序数组中两个值相加为k的数字,返回这两个数字的下标。
//找到返回正常的下标,查找失败返回-1
Pairs SumToK(int *arr,int len,int k)//时间复杂度O(n),空间复制度O(1)
{
Pairs pa = {-1,-1};
int low = 0; //从前往后遍历
int high = len-1;//从后往前遍历
int sum;
while(low <= high)
{
sum = arr[low] + arr[high];
if(sum < k)
{
low++;
}
else if(sum > k)
{
high--;
}
else
{
pa.x = low;
pa.y = high;
break;
}
}
return pa;
}
int main()
{
int arr[] = {1,3,5,6,17,18,29,33,44,55,89};
int k = 9;
Pairs pa = SumToK(arr,sizeof(arr)/sizeof(arr[0]),k);
if(pa.x == -1)
printf("没有两数相加等于%d\n",k);
else
printf("相加等于%d的为%d,%d下标的值\n",k,pa.x,pa.y);
k = 50;
pa = SumToK(arr,sizeof(arr)/sizeof(arr[0]),k);
if(pa.x == -1)
printf("没有两数相加等于%d\n",k);
else
printf("相加等于%d的为%d,%d下标的值\n",k,pa.x,pa.y);
k = 4;
pa = SumToK(arr,sizeof(arr)/sizeof(arr[0]),k);
if(pa.x == -1)
printf("没有两数相加等于%d\n",k);
else
printf("相加等于%d的为%d,%d下标的值\n",k,pa.x,pa.y);
k = 1;
pa = SumToK(arr,sizeof(arr)/sizeof(arr[0]),k);
if(pa.x == -1)
printf("没有两数相加等于%d\n",k);
else
printf("相加等于%d的为%d,%d下标的值\n",k,pa.x,pa.y);
}
//TODO,如果相加为k的有多组,上面的算法并没有实现,例如k=50,有6+44,17+33
//2.2,如果是无序的数组呢?
//算法分析:1.如果都是非负的数字,则可以建立一个k长度的哈希表,哈希表中每个元素保存值和下标,遍历整个数组一遍把大于k的值直接丢弃(相加不可能为k)小于等于k的值保存到哈希表,然后利用上面的算法遍历哈希表即可.