完美校招的职位仅仅三个: c++ 、java、 游戏策划(总之一句话,基础非常重要,而且一定要精通一门语言)
问题一:给出一个十六进制的数0xFF 0x80 (只有2“位”) 将其转换成有符号的一字节的十进制整数
解:因为是转成有符号数,所以,可以先将其转成二进制
如:0xFF->1111 1111
可见符号位为1,为负数,负数是以补码存储的,所以求其原码
补码减一 取反即为原码 1111 1110 ->1000 0001 -> -1 取反时符号位不变
0x80 1000 0000
符号位1 是负数 求原码: 0111 1111 -> 1000 0000 -128
0x00 0000 0000 符号位为0 补码即原码 0000 0000 -> 0
0x7F 0111 1111 符号位为0 0111 1111 ->127
一字节数中 0x00~0x79 为0~127 0x80~0xFF 为 -128~ -1
知识补充:
补码在微型机中是一种重要的编码形式,请注意:
a. 采用补码后,可以方便地将减法运算转化成加法运算,运算过程得到简化。正数的补码即是它所表示的数的真值,而负数的补码的数值部份却不是它所表示的数的真值。采用补码进行运算,所得结果仍为补码。
b. 与原码、反码不同,数值0的补码只有一个,即 [0]补=00000000B。
c. 若字长为8位,则补码所表示的范围为-128~+127;进行补码运算时,应注意所得结果不应超过补码所能表示数的范围。
问题二:3*(4+6)-7 # 用代码实现这个运算表达式
第一步由中缀表达式求逆波兰式
用数组suffix[]存放逆波兰表达式,用栈optstack存放运算符
遇到数字则直接放入数组suffix;遇到运算符号,先与optstack的栈顶运算符比较优先级,高于栈顶优先级,则入栈,否则optstack符号栈出栈,直到当前运算符高于栈顶优先级;
suffix:3 4 6
optstack:* ( +
遇到)则符号栈出栈(不加入suffix),+ 并加入suffix 至(,左括号出栈(不加入suffix)
suffix: 3 4 6 +
optstack: *
由于 - (减号)低于栈顶符号,optstack符号栈继续入栈,直到减号的优先级大于栈顶的; 减号 - 入optstack栈,后面的数字直接进入suffix
suffix: 3 4 6 + * 7
optstack: -
直至遇到终结符#, 将符号栈optstack的所有元素依次出栈,并依次加入数组suffix[]中
suffix : 3 4 6 + * 7 -
此时逆波兰式 已经建立完成 开始运算
第二步 求逆波兰表达式的值
建立一个 运算栈s ,依次扫描suffix逆波兰表达式,若为数字则直接入栈s;若为运算符则运算栈弹出两个数字,并计算,把新的值压入运算栈s
s : 3 4 6
直至遇到符号+ ,s连续出栈2次
计算4+6 ->10 然后将新数据入栈s
s: 3 10
遇到*s,连续出栈2次
计算3*10 ->30 ,然后压栈
S:30
继续遵循此规则直至栈d为空,s最终会只有一个数,即为答案
知识补充:
(1)由一个表达式(中缀表达式)求其后缀表达式(即逆波兰表达式)
方法一:通过 二叉树可以实现其对应的
二叉树的根节点必定是优先级最低的操作符(也就是说是整个表达式中最后进行的运算操作),然后再在操作符的左部分中找出最后进行的操作符作为根节点的左孩子,在操作符的右部分中找出最后进行的操作符作为根节点的右孩子,然后知道左部分或者右部分是单纯的操作数,则作为叶子节点,直到整个二叉树建立完毕;
方法二:利用栈进行转换
利用栈进行转换的思路其实跟前面直接对中缀表达式求值的过程类似,在这过程中需要一个栈用来保存操作符optStack,需要一个数组用来保存后缀表达式suffix[],然后从头到尾扫描表达式
1)如果遇到操作符,则跟optStack的栈顶操作符比较优先级,如果大于栈顶操作符的优先级,则入栈,否则不断取栈顶操作符加到suffix的末尾,直到栈顶操作符优先级低于该操作符,然后将该操作符入栈;
2)遇到操作数,直接加到suffix的末尾
3)遇到左括号,入栈;
4)遇到右括号,则依次弹出栈顶操作符加到suffix的末尾,直到遇到左括号,然后将左括号出栈。
(2) 给定一个逆波兰表达式(即后缀表达式),求该表达式的值
可以直接利用栈来模拟计算:遇到操作数直接压栈,碰到操作符直接取栈顶的2个操作数进行计算(注意第一次取出来的是右操作数),然后再把计算结果压栈,如此循环下去。最后栈中剩下的唯一一个元素便是整个表达式的值。
(3) 直接计算中缀表达式
如果复杂一点,比如包含有括号,连续的乘除法这些怎么处理呢?道理是一样的,对于左括号直接入栈,碰到右括号,则一直将操作符退栈,直到碰到左括号,则括号中的表达式计算完毕。对于连续的乘除法,跟前面例子中处理过程类似。只需要记住一点:只有当前操作符的优先级高于操作符栈栈顶的操作符的优先级,才入栈,否则弹出操作符以及操作数进行计算直至栈顶操作符的优先级低于当前操作符,然后将当前操作符压栈。当所有的操作符处理完毕(即操作符栈为空时),操作数栈中剩下的唯一一个元素便是最终的表达式的值。而操作符的优先级为:+和-优先级是一样的,*和/优先级是一样的,+、-的优先级低于*、/的优先级。
不过需要注意的是在求值之前需要对表达式进行预处理,去掉空格、识别 负号(区分“-”是作为减号还是负号),提取操作数等。
问题三:有一组数, 给出其赫夫曼编码 要求平均权值最小
如: 3 7 9 1 12 根据其大小建立赫夫曼树,再求起其赫夫曼编码
1:1111
3:1110
7: 110
9: 10
12: 0
知识补充:
哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。
显然哈夫曼编码是前缀编码,即任一个字符的编码都不是另一个字符的编码的前缀,否则,编码就不能进行翻译。
问题四:c++中的虚继承
1、虚继承的作用
2、多继承时的二义性等
3、对虚基类的了解
问题五:单例模式
public static class Singleton{ private static Singleton instance = null; private Singleton(){ //dosomething } public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
问题六:使一个类的实例 只能在堆中分配内存 不能在栈中分配内存
class A{};
A a = new A 是在堆中分配内存
A b; 是在栈中分配内存 调用其默认构造函数
所以将其默认构造函数声明为private就可以
总之,问的问题比较偏重基础的,面也比较广,涉及到了数据结构、编译原理、组成原理、操作系统、计算机网络等,还有一些c++语法,java的设计模式。