CVTE 2017 内推笔试整理

来源:互联网 发布:贷款买车用什么软件 编辑:程序博客网 时间:2024/05/16 02:17

CVTE 笔试整理

选择题

C 类网络划分子网

问题:

C 类网络,要求子网不小于 8 个,主机号不少于 14 个,哪些能作为子网掩码

回答:

从问题可得知,子网不小于 8 个,则子网号的位数至少要有 3 位;主机号不少于 14 个,则主机号的位数至少要有 4 位,因此可以作为子网掩码的是255.255.255.224 和 255.255.255.240

知识点整理:
IP 地址分为 A、B、C、D、E 类地址,每个 IP 地址由 32 位组成,A、B、C 类 IP 地址由网络号和主机号组成

  • A 类:

这里写图片描述

  • B 类:

这里写图片描述

  • C 类:

Alt text

划分子网
  由于我们使用的 IP 地址都属于两级 IP 地址(网络号+主机号),该种结构的 IP 地址存在很多缺点: 
  
1. IP 地址空间的利用率有时很低,
  如一个 A 类地址可以有 2^24-2 个主机,B 类地址可以有 2^16 -2 个主机,一般一个以太网最大的结点数会有限制,因此使用 A、B 类会造成浪费,使用 C 类又担心不够用,利用率会降低
  
2. 给每一个物理网络分配一个网络号会导致路由表太大
3. 两级 IP 地址不够灵活

  因此为了解决这些问题,采用了划分子网的方式来,将 IP 地址设计为三级结构(网络号+子网号+主机号),使用主机号的若干位作为子网号,剩余的作为主机号。

报文传输:
  报文在发送到该网络上时,会再根据子网号转发到对应的子网,来发送到对应的主机。

那么,发送到该网络上的报文,如何转发到对应的子网?
  在此基础上,增加子网掩码,子网掩码也是由 32 位组成,B 类地址的子网掩码是 255.255.0.0,C 类地址的子网掩码是 255.255.255.0,划分子网后的子网掩码只需要将子网号对应的位变为 1 即可,则 C 类地址,三位子网号的子网掩码是 255.255.255.11100000,要计算报文属于哪个子网,只需要将报文的目的 IP 地址与子网掩码做 & 运算即可得到目标子网。一般子网号不能全为 0 或全为 1。

总结:
  对于划分子网问题,只需要根据子网掩码来计算出子网号和主机号各有多少位即可解决

synchronized 和 lock

问题:

该题主要是考察 synchronized 和 lock 的区别,具体选项忘记了。

关于 synchronized 和 lock 的区别的知识点之后再整理

反射机制

  在 Java 中,我们要使用一个对象时,需要编译器在编译时打开和检查 .class 文件,加载进 JVM 才能使用。反射机制允许我们不需要再编译时加载类,而是在运行时才加载类,同时通过反射,可以获取类的信息,来动态的创建和操作对象。
反射机制的功能:

  • 可以获取类名和类的继承结构
  • 可以创建类的实例
  • 可以获取类定义的方法、字段和构造器(包括私有的)
  • 可以调用类的方法
  • 可以获取类加载器

Java 的 hashcode

问题:

该题主要考察 hashcode 的规则以及特点,是一道判断对错题,以下选项1. String 没有重写 hashcode 方法2. 空字符串的 hashcode 值相等3. hashcode 方法一定要返回一个确切的整数 4. 当对象的 equal 方法返回 true 时,那么它们的 hashcode 也应该相同

  当时我纠结了很久,1 是否正确。主要是因为对 String 的源码不熟悉以及不了解 hashcode 的设计规范。

首先,先看看 Object 类中定义的 hashcode 方法

 public native int hashCode();

它是一个本地方法,从方法签名中可以知道 hashcode 方法返回一个整数,而且同一个对象返回相同的 hashcode(这是 Java 中 hashcode 的机制)。

在看看 String 类中的 hashcode 方法

 public int hashCode() {        int h = hash;        if (h == 0 && value.length > 0) {            char val[] = value;            for (int i = 0; i < value.length; i++) {                h = 31 * h + val[i];            }            hash = h;        }        return h;    }

  该方法计算 hash 值与你字符串的内容有关。因此 String 类有改写它的 hashcode 方法。还有另外一种判断方法,在 hashcode 的规范中,如果两个对象的 equal 方法返回 true,那么这两个对象 hashcode 方法也应该相等。String 类的 equal 方法是只要字符串内容相同,则返回 true。
  因此当两个对象拥有相同的字符串时,它们的 hashcode 相等,如果没有重写 hashcode 方法,两个不同对象应该会有不同的 hashcode 值,所以 String 方法是有重写 hashcode 方法的。

ping 命令

问题:

ping 命令是采用哪种 ICMP 报文?

回答:

  该题目考察的是 ping 命令的机制以及 ICMP 的报文类型,首先我们应该要了解 ping 命令的功能是什么。学过计网的或者是使用过 ping 命令的人应该都知道,ping 命令是用于测试能否连接某一主机。  如在 cmd 中输入 ping 192.168.1.111之后,然后它会尝试去连接 IP 地址为 192.168.1.111 的主机,然后返回连接结果和延迟时间。  我记得在该题上,有两个选项是一个是报文不可达,一个是 echo报文回显,当时我选的是报文不可达,因为我想测试是否连接成功,报文不可达则代表连接失败。结果是 echo 报文回显。纯属理论题,需要对 ICMP 各个报文类型的功能有足够的了解。

知识点整理:
ICMP 报文
  ICMP 报文主要有两种类型,一种是 ICMP 差错报告报文,另一种是 ICMP 询问报文。
  
常见的 ICMP 差错报文类型

  • 终点不可达:当路由器或主机不能交付数据报时就向源点发送终点不可达报文
  • 源点抑制:当路由器或主机由于阻塞而丢弃数据报时,就向源点发送源点抑制报文,使源点知道应当把数据报的发送速率放慢
  • 时间超过:当路由器收到生存时间为 0 的数据包时,除丢弃该数据报外,还要向源点发送时间超过报文(当终点在规定时间,数据报片未来齐,也会发送)
  • 参数问题:当路由器或目的主机收到的数据包的首部中有的字段不正确时,就丢弃该数据报,并向源点发送参数问题报文
  • 改变路由(重定向):路由器把改变路由报文由报文发送给主机,让主机知道下次应将数据报发送给另外的路由器

常见的 ICMP 询问报文类型

  • 回送请求和回答:向一个特定的目的主机发出询问,用于测试目的主机是否可达以及了解其有关状态
  • 时间戳请求和回答:请求某个主机或路由器返回当前日期和时间

Java 类库的设计模式

问题:

该题主要考察对设计模式的了解以及 Java 类库中的实现方式,具体选项忘记了,好像有提到单例模式、桥接模式、原型模式

关于设计模式的整理之后在其他文章整理

编程题

解压字符串

问题:

aa 解压成 2[a],即把连续相同的字符串压缩成 k[abc] 的形式,现实现一个算法来解压字符串输入 2[a]2[b],则输出 aabb输入2[ab3[c]a],则输出 abcccaabccca

解答:
  该题目主要考察递归的思想,字符串被压缩成 k[abc] 的形式,则将其解压还原成 k 个 abc 的字符序列,那么我们的主要思路就是找到字符串中哪些字符被压缩(即有多少个 k[abc] 形式的字符),然后将其解压还原出来。那么该问题就转化成找 k[abc] 序列

算法思路就是:
对于字符串每一个字符 i:
1. 如果当前字符是数字,就使用 num 记录起来(num = num*10 + s[i] - ‘0)’,记作 k,然后遍历下一个字符
2. 如果 num > 0,下一个字符不是 ‘[‘,则代表前面数字字符是直接输入的,则将 num 序列输出,num 置 0,并将当前字符也输出
3. 如果 num > 0,下一个字符是 ‘[‘则代表该处可能是被压缩的字符串,则从此处开始向后寻找字符,一直到寻找到与它对应的 ‘]’ 结束,若找得到 ‘]’,则将找到的字符序列输出 num 次,若找不到,代表该处并不是压缩的,直接输出num 和 ‘[’ 和找到的字符串
4. 如果 num <= 0,且该字符不是 ‘[‘,则直接输出

通过看以上分析,如果并不能看出整体思路,可以尝试举一些例子来手动模拟过程。下面以 2[ab3[c]a] 为例子来说明该过程:

String = 2[ab3[c]a],length = 10
初始时 num = 0
1. 遍历第一个字符 2,由于它是数字,则num 记录,此时 num = 2
2. 遍历第二个字符 [,因为当前 num = 0 > 2,则需要向后查找 [] 的序列
 2.1 第三个字符 a,不是],直接输出,此时字符序列是 a
 2.2 第四个字符是b,不是],直接输出,此时字符序列是 ab
 2.3 第5个字符是 3,是数字,则用 num 记录,此时 num = 3
 2.4 第6个字符是 [,当前 num = 3 > 0,则又需要向后查找 [] 的序列
   2.4.1 第 7 个字符是 c,不是 ],直接输出,此时字符序列是 c
   2.4.2 第 8 个字符是 ],则找到了,此时结束了,返回字符序列 c
 2.5 找到的序列是 c,因此输出 3 * c,此时序列是 abccc
 2.6 第 9 个字符是 a,直接输出,此时序列是 abccca
 2.7 第 10 个字符是 ],找到结束了,返回字符序列 abccca
3. 找到的序列是 abccca,则输出 2 * abccca,则输出 abcccaabccca
4. 此时已经到达了字符串的尾端,则解压完毕

从上述过程,我们可以看到,我们在寻找 [] 内的序列时,可能内层还嵌套了 [],而且每一次 num 都可能不相同,因此我们需要使用递归的方式来解决该问题

以下是我用 Java 写的代码,不好的地方请指出,另外我使用了两个全局变量,这是我觉得不太好的地方,如果你们更好的想法,可以提出来大家交流交流。

public class UnzipString {    private int index = 0;    private int level = 0;    public String unzip(String str) {        index = 0;        level = 0;        return unzipString(str);    }    public String unzipString(String str) {        // 判断字符串是否为空        if (str == null || "".equals(str)) {            return "";        }        // 用于记录我递归进入函数时,当前第一个字符是原字符的第几个位置        int beginIndex = index;        StringBuilder buffer = new StringBuilder();        int length = str.length();        char[] s = str.toCharArray();        int num = 0;        for (int i = 0; i < length; i++, index++) {            // 如果当前字符是数字,是数字则用 num 记录            if (s[i] >= '0' && s[i] <= '9') {                num = num * 10 + (s[i] - '0');                // 如果当前 num 大于 0 ,而数字后面不是 [,则 num 和字符属于直接输出的            } else if (num > 0 && s[i] != '[') {                buffer.append(num);                buffer.append(s[i]);                num = 0;            // 如果当前 num > 0,且num 后面接的是 [,则开始递归寻找 [] 的字符            } else if (num > 0 && s[i] == '[') {                level++;                index++;                String compressStr = unzipString(str.substring(i + 1));                i = index - beginIndex;                // 判断是否因为有匹配的 ']' 而退出,若不是,则代表该字符串并不是压缩的,而是直接输出的                if (i < length && s[i] == ']') {                    for (int j = 0; j < num; j++) {                        buffer.append(compressStr);                    }                } else {                    buffer.append(num);                    buffer.append('[');                    buffer.append(compressStr);                }                level--;                num = 0;            // 如果当前是有递归进入寻找 [] 序列,且当前字符是 ],则代表该层的序列已找到,可返回            } else if (level > 0 && s[i] == ']') {                return buffer.toString();            } else {                buffer.append(s[i]);            }        }        return buffer.toString();    }}

分析获取课程信息的方式

分析一下方式的优缺点
1. 抓取学校相关网页的信息
2. 使用教务管理系统接口 API
3. 直接从数据库获取

该题目是论述题,我是从这些方式的特点从开发、维护和数据隐私的方面论述的。具体就不写了,大家可以讨论一下自己的看法

密码是否满足

题目要求:

1. 密码长度要在 8-16位2. 密码至少要包含大写、小写、特殊符号(!@#$%^&*) 、数字三种3. 不能有连续相同字符串

解答:
  该题目主要考察的是正则表达式的使用,如果熟悉正则表达式,则使用正则匹配则可完成以上要求的判断,若是不会,也可以使用比较基础的方法去比较。
  具体正则的知识点和Java Pattern 和 Matcher 的用法自行去百度或者 google 吧。

以下是我的代码

private Pattern upcaseP = Pattern.compile("[A-Z]");    private Pattern lowcaseP = Pattern.compile("[a-z]");    private Pattern specChapP = Pattern.compile("[!@#$%^&*]");    private Pattern numP = Pattern.compile("\\d");    private Pattern sameStrP = Pattern.compile("([a-zA-Z0-9!@#$%^&*]+)\\1");    public boolean checkPassword(String password) {        // 判断密码长度是否在8-16位        int length = password.length();        if (length < 8 || length > 16) {            return false;        }        // 记录大写、小写、特殊字符、数字有多少匹配        int matches = 0;        Matcher upcaseM = upcaseP.matcher(password);        Matcher lowcaseM = lowcaseP.matcher(password);        Matcher specCharM = specChapP.matcher(password);        Matcher numM = numP.matcher(password);        if (upcaseM.find()) {            matches++;            System.out.println("大写匹配");        }        if (lowcaseM.find()) {            matches++;            System.out.println("小写匹配");        }        if (specCharM.find()) {            matches++;            System.out.println("特殊字符匹配");        }        if (numM.find()) {            matches++;            System.out.println("数字匹配");        }        if (matches < 3) {            return false;        }        // 判断连续相同字符串        Matcher sameStrM = sameStrP.matcher(password);        if (sameStrM.find()) {            return false;                }          ··        return true;    }}

总结

  这次投的是 CVTE 的后台研发岗位,选择题考的内容主要是 Java 的基础知识点(计网有 2 题,数据结构也有几道,忘了,考的是二叉树的后序遍历),编程题则考了正则和递归。
  在这次笔试中,这也是第一次笔试,其实暴露出自己很多问题,第一编程题能力弱,在做编程题时,没有好好分析编程题的思路就开始动手,导致后面越写越乱,都不知道怎么去修改了,所以下次做编程题的时候应该先把问题的思路理清楚,然后才再开始编码。另外还暴露出一个致命的问题就是基础不够扎实,在做选择题的时候,对很多选项的知识点似曾相识,感觉肯定在哪里看过,但是又不能确定是对还是错,所以基础真的很重要。
  

1 0
原创粉丝点击