【2020年数据结构真题】

179 阅读3分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 18 天,点击查看活动详情

41题(13分)

定义三元组(a,b,c)(a、b、c均为正数)的距离D=|a-b|+|b-c|+|c-a|给定3个非空整数集合S1、S2和S3,按升序分别存储在3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)(a∈S1,b∈S2,C∈S3)中的 最小距离。例如S1 ={-1,0,9},S2={-25,-10,10,11),S3={2,9,17,30,41},则最小距离为2,相应的三元组为(9,10,9)。

要求:

  1. 给出算法的基本设计思想。

  2. 根据设计思想,采用C语言或C++语言描述算法,关键之处给出注释。

  3.  说明你所设计算法的时间复杂度和空间复杂度。

前提

  • 尽可能高效 那意思不高效就扣几分
  • 按照升序存储
  • 最小距离

除了算最小距离,我们还需要记录这三个元素。最简单的办法即取出每种组合,套公式来判断。  

暴力解

typedef struct 
{
    int a,b,c;          
    int value; 
} Triple;



Triple func(int S1[],int S2[],int S3[],int n1,int n2,int n3){
    Triple T;
    T.value=INT_MAX;
    for(int i=0;i<n1;++i){
        for(int j=0;j<n2;++j){
            for(int k=0;k<n3;++k){
                int D=(abs(S1[i]-S2[j])+abs(S1[i]-S3[k])+abs(S2[j]-S3[k]));
                //abs是绝对值函数
                if(D<T.value){
                    T.value=D;
                    T.a=S1[i];
                    T.b=S2[j];
                    T.c=S3[k];
                }
            }
        }
    }
    return T;
}

时间复杂度为O(n³)

官方解析:可不看 直接暴力解7-8分省很多时间

image.png

42题(10分)

若任一个字符的编码都不是其他字符编码的前缀,则称这种编码具有前缀特性。现有某字符集(字符个数>2)的不等长编码,每个字符的编码均为二进制的 01序列,最长为L位,且具有前缀特性。请回答下列问题:

  1. 哪种数据结构适宜保存上述具有前缀特性的不等长编码?

  2. 基于你所设计的数据结构,简述从0/1串到字符串的译码过程

  3. 简述判定某字符集的不等长编码是否具有前缀特性的过程

解答:

  1. 使用一棵二叉树保存字符集中各字符的编码,每个编码对应于从根开始到达某叶结点的一条路径,路径长度等于编码位数,路径到达的叶结点中保存该编码对应的字符。

  2. 从左至右依次扫描 0/1 串中的各位。从根开始,根据串中当前位沿当前结点的左子指针或右子指针下移,直到移动到叶结点时为止。输出叶结点中保存的字符。然后从根开始重复这个过程,直到扫描到 0/1 串结束,译码完成。

  3. 二叉树既可用于保存各字符的编码,又可用于检测编码是否具有前缀特性。判定编码是否3具有前缀特性的过程,也是构建二叉树的过程。初始时,二叉树中仅含有根结点,其左子指针和右子指针均为空。


依次读入每个编码C,建立/寻找从根开始对应于该编码的一条路径,过程如下:

对每个编码,从左至右扫描C的各位,根据C的当前位(0或1)结点的指针(左子指针或右子指针)向下移动。当遇到空指针时,创建新结点,让空指针指向该新结点并继续移动。沿指针移动的过程中,可能遇到三种情况:

  • 若遇到了叶结点(非根),则表明不具有前缀特性,返回。
  • 若在处理 C的所有位的过程中,均没有创建新结点,则表明不具有前缀特性,返回
  • 若在处理的最后一个编码位时创建了新结点,则继续验证下一个编码。

若所有编码均通过验证,则编码具有前缀特性。