能否快速找出一个数组中的两个数,让这两个数之和等于一个给定的数字,为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解。
解题思路:
可以先将数组升序排序,然后设定变量i = 0,j = size - 1,看array[i] + array[j] 是否等于sum, 如果相等,则结束。如果小于sum,则 i = i + 1; 如果大于sum,则 j = j - 1。这样只需要在排好序的数组上遍历一次就可以得到最后的结果,时间复杂度为O(n), 加上排序的时间复杂度,总的复杂度为O(n*log2n)。
【代码】
#include <stdio.h>
void swap(int array[],int low,int high)
{
int temp;
temp=array[low];
array[low]=array[high];
array[high]=temp;
}
void quicksort(int array[],int low,int high)
{
int i=low,j=high;
int pivot;
int pivotkey;
pivotkey=array[low];
if(low<high)
{
while(i<j)
{
while(i<j&&array[j]>=pivotkey)
j--;
swap(array,i,j);
while(i<j&&array[i]<=pivotkey)
i++;
swap(array,i,j);
}
pivot=i;
quicksort(array,low,pivot-1);
quicksort(array,pivot+1,high);
}
}
int sum2(int array[],int size,int sum,int index1[],int index2[])
{
int i=0;
int j=size-1;
int k=0;
while(i<j)
{
if((array[i]+array[j])>sum)
j--;
else if((array[i]+array[j])<sum)
i++;
else
{
index1[k]=i;
index2[k]=j;
k++;
i++;
j--;
}
}
return k;
}
void main()
{
int a[6]={6,8,-3,0,2,4};
int i;
quicksort(a,0,5);
for(i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
int index1[6];
int index2[6];
int result;
result=sum2(a,6,10,index1,index2);
printf("%d\n",result);
for(i=0;i<result;i++)
printf("%d %d\n",a[index1[i]],a[index2[i]]);
printf("\n");
}
输出为[-3,0,2,4,6,8]
2 8
4 6
问题?如果[-3,0,2,2,8,8]
输出2 8
2 8
即可能有重复的情况。
int sum2(int array[],int size,int sum,int index1[],int index2[])
{
int i=0;
int j=size-1;
int k=0;
while(i<j)
{
if((array[i]+array[j])>sum)
{
//注意,跳过重复的元素
while(i<j&&array[j]==array[j-1])
{
j--;
}
j--;
}
else
{
if((array[i]+array[j])<sum)
{
//注意,跳过重复的元素
while(i<j&&array[i]==array[i+1])
{
i++;
}
i++;
}
else
{
index1[k]=i;
index2[k]=j;
k++;
//注意,跳过重复的元素
while(i<j&&array[j]==array[j-1])
{
j--;
}
while(i<j&&array[i]==array[i+1])
{
i++;
}
i++;
j--;
}
}
}
return k;
}