数据结构的算法习题

线性表

#本文采用伪代码

1.定义三元组(a,b,c)(a,b,c均为整数)的距离D=| a-b |+|b-c|+|c-a|。给定三个非空整数集合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)。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值