线性表
#本文采用伪代码
1.定义三元组(a,b,c)(a,b,c均为整数)的距离D=。给定三个非空整数集合S1,S2和S3,按升序分别存储在3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)(a,b,c分别是S1,S2,S3中的元素)中的最小距离。例如S1={-1,0,9},S2={-25,-10,10,11},S3={2,9,17,30,41},则最小距离为2,相应的三元组为(9,10,9)。
算法思想:通过条件进行分析,由D的关系式可以知道,当定义的a=b=c时D的值最小,不理解的话可以通过画数轴理解一下,实际上决定D值大小的关键就是a和c之间的距离,于是这个问题就可以转化为每次固定c找一个a来使c-a的绝对值最小。
#define INT_MAX 999999
int abs_(int a){//计算绝对值
if(a<0) return -a;
else return a;
}
bool xls_min(int a,int b,int c){//判断a是否是三个数中的最小值
if(a<=b&&a<=c) return true;
return false;
}
int findMIN(int A[],int n ,int B[],int m,int C[],int p){//用D_min记录最小值,初始值就是999999
int i=0,j=0,k=0,D_min=INT_MAX,D;
while(i<n&&j<m&&k<D_min>0){
D=abs_(A[i]-B[j])+abs_(B[j]-C[k])+abs_(C[k]-A[i]);//计算D的值
if(D<D_min) D_min=D;//如果有比上次的D_min更小的D就更新值
if(xls_min(A[i],B[j],C[k])) i++;//类似上面更新a的值
else if(xls_min(B[j],C[k],A[i]))
j++;
else
k++;
}
return D_min;
}
该算法的时间复杂度为O(n),空间复杂度O(1)。
2.设有一个长度为n(n为偶数)的不带头结点的单链表,且结点值都大于0,设计算法求这个单链表的最大孪生和。孪生的定义为一个结点值与其孪生结点值之和,对于第i个结点(从0开始),其孪生结点为第n-i-1个结点。
基本思想:采用快慢指针
算法设计:设置快、慢两个指针分别为fast和slow,初始时slow指第一个结点,fast指第二个结点,slow每走一步,fast走两步。当fast走到结尾时。slow正好走到一半(第n/2个结点)。将链表的后半部分逆置,然后设置两个指针分别指向链表的前半部分和后半部分的首结点,在遍历过程中计算两个指针所指结点的元素之和,并维护最大值。
int PairSun(LinkList L){
LNode *fast=L->next,*slow=L;//定义我们算法中的快慢指针
while(fast!=MULL&&fast->next!=NULL){
fast=fast->next->next;//走两步
slow=slow->next;//走一步
}
LNode *newHead=NULL,*p=slow->next,*tmp;//多余结点用于缓冲
while(p!=NULL){//反转链表后一半部分的元素,采用头插法
tmp=p->next;//p指向当前待插入结点,令tmp指向其下一结点
p->next=newHead;//将p所指向结点插入到新链表的首结点之前
newHead=p;//newHead指向刚才新插入的结点,作为新的首结点
p=tmp;//当前待处理结点变为下一结点
}
int max=0; p=L;
LNode *q=newHead;
while(p!=NULL){//用p和q分别便利两个链表
if((p->data+q->data)>max)//max是最大值
max=p->data+q->data;
p=p->next;
q=q->next;
}
return max;
}
此算法的时间复杂度为O(n),空间复杂度为O(1)。