在构建哈夫曼树时,每次应该选择( )合并。
A:最小权值的节点。哈夫曼算法每步从森林中选出权值最小的两个结点合并,让高频率字符离根近、编码短,从而保证带权路径长度最小。
面向对象的编程思想主要包括以下哪些原则( )?
D:封装、继承、多态。封装隐藏内部实现、继承实现代码复用、多态让同一接口呈现不同行为,是 OOP 三大特性;其余选项分别是算法与并发概念。
在队列中,元素的添加和删除是按照( )原则进行的。
A:先进先出。队列在队尾入队、队头出队,先入队的元素先被取出,即 FIFO;先进后出是栈的性质,最小值先出是优先队列,与普通队列不符。
给定一个简单的类定义如下,( )语句在类的外部正确地创建了一个 Circle 对象并调用了 getArea 函数?
01class Circle { 02private: 03 double radius; 04public: 05 Circle(double r) : radius(r) {} 06 double getArea() { 07 return 3.14 * radius * radius; 08 } 09};
D:Circle c(5.0) 调用单参构造函数创建对象,c.getArea() 通过对象调用成员函数;A 的 getArea(c) 多传了参数、B 把成员函数当普通函数调用、C 中 new 返回指针不能赋给对象,均错。
以下代码希望能在一棵二叉排序树中搜索特定的值,请在横线处填入( ),使其能正确实现相应功能。
01TreeNode* search(TreeNode* root, int target) { 02 if (root == NULL || root->val == target) { 03 return root; 04 } 05 if (____________) { 06 return search(root->left, target); 07 } else { 08 return search(root->right, target); 09 } 10}
B:target<root->val。BST 中左子树值小于根,目标比根的值小就递归查左子树,否则查右子树;比较对象是 root->val,A、D 拿指针 root->left 比较是错的。
3 位格雷编码的正确顺序是( )。
B:格雷码相邻编码只差一位。B 中 000→001→011→010→110→111→101→100 每步只翻转一位;A 是二进制自然序,C、D 存在一次变多位的跳变。
以下动态规划算法的含义与目的是( )。
01int function(vector<int>& nums) { 02 int n = nums.size(); 03 if (n == 0) 04 return 0; 05 if (n == 1) 06 return nums[0]; 07 vector<int> dp(n, 0); 08 dp[0] = nums[0]; 09 dp[1] = max(nums[0], nums[1]); 10 for (int i = 2; i < n; ++i) { 11 dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]); 12 } 13 return dp[n - 1]; 14}
C:dp[i]=max(dp[i-1], nums[i]+dp[i-2]):不选第 i 个继承 dp[i-1],选它则加上跳过一个的 dp[i-2],即求数组中不相邻元素的最大和(打家劫舍问题)。
阅读以下广度优先搜索的代码:
01void bfs(TreeNode* root) { 02 if (root == NULL) { 03 return; 04 } 05 queue<TreeNode*> q; 06 q.push(root); 07 while (!q.empty()) { 08 TreeNode* current = q.front(); 09 q.pop(); 10 cout << current->val << " "; 11 if (current->left) { 12 q.push(current->left); 13 } 14 if (current->right) { 15 q.push(current->right); 16 } 17 } 18}
使用以上算法遍历以下这棵树,可能的输出是( )。
1
/ \
2 3
/ \ \
8 9 6
/ \ \
4 5 7
/ \
10 11
C:BFS 按层输出:第 1 层 1,第 2 层 2 3,第 3 层 8 9 6,第 4 层 4 5 7,第 5 层 10 11,合并为 1 2 3 8 9 6 4 5 7 10 11。
给定一个空栈,执行以下操作序列:
操作序列:push(1), push(2), push(3), pop(), pop(), push(4), push(5), pop()
最终栈中的元素是( )。
D:模拟栈:压入 1、2、3 后弹出两次(3、2)剩 [1],压入 4、5 再弹一次(5)剩 [1,4],最终栈中元素为 1,4。
一个有 124 个叶子节点的完全二叉树,最多有( )个结点。
B:248。叶子 124 个,由 n0=n2+1 得 n2=123;完全二叉树度为 1 的结点最多 1 个,总结点数=124+123+1=248。
在求解最优化问题时,动态规划常常涉及到两个重要性质,即最优子结构和( )。
A:重叠子问题。DP 求解最优化问题依赖两个性质:最优子结构(最优解含子问题最优解)与重叠子问题(子问题被反复求解,用表记忆化);分治、贪心、回溯不是 DP 的性质。
若一棵二叉树的先序遍历为:A, B, D, E, C, F,中序遍历为:D, B, E, A, F, C,它的后序遍历为( )。
A:由先序知根为 A,中序 DBE 在左、FC 在右;左子树先序 BDE、中序 DBE,B 为左根,D、E 是其左右孩子;右子树先序 CF、中序 FC,C 为右根、F 为其左孩子;后序得 D E B F C A。
线性筛法与埃氏筛法相比的优势是( )。
C:更快速。线性筛让每个合数只被其最小质因子筛掉一次,复杂度 O(n),比埃氏筛 O(n log log n) 更快;它实现更复杂,内存相当,准确性无差别。
以下代码使用了辗转相除法求解最大公因数,请在横线处填入( ),使其能正确实现相应功能。
01int gcd(int a, int b) { 02 while (b != 0) { 03 ____________ 04 } 05 return a; 06}
C:用 temp 暂存旧 b,b 更新为 a%b,再把 a 置为旧 b,完成 gcd(a,b)=gcd(b,a%b);A、B 用了除法 a/b,D 的 a=b 用的是已更新过的 b,均错。
下面的代码片段用于反转单链表,请进行( )修改,使其能正确实现相应功能。
01ListNode* reverseLinkedList(ListNode* head) { 02 ListNode* prev = nullptr; 03 ListNode* current = head; 04 while (current != nullptr) { 05 ListNode* next = current->next; 06 current->next = next; 07 prev = current; 08 current = next; 09 } 10 return prev; 11}
A:反转链表要把当前结点的 next 指向前驱 prev,原代码写成 current->next=next 相当于没改;B、C、D 的改动都会破坏遍历或反转的正确性。
哈夫曼树是一种二叉树。
A:正确。哈夫曼树是带权路径长度 WPL 最小的二叉树,每次合并两个最小权值结点生成新结点,所有结点度为 0 或 2,本质就是二叉树。
在动态规划中,状态转移方程的作用是定义状态之间的关系。
A:正确。状态转移方程描述当前状态如何由前面的状态递推得到,如 dp[i]=dp[i-1]+dp[i-2],正是动态规划定义状态间关系的核心。
继承是将已有类的属性和方法引入新类的过程。
A:正确。继承让派生类自动获得基类的属性和方法,并可扩展新成员或重写行为,是把已有类的成员引入新类、实现代码复用的机制。
完全二叉树的任意一层都可以不满。
B:错误。完全二叉树除最后一层外每层都必须排满,最后一层允许不满但结点必须从左到右连续排列;「任意一层都可以不满」把限制放宽到所有层,说法错误。
删除单向链表中的节点,只需知道待删除节点的地址即可,无需访问前一个节点。
B:错误。单链表删除节点需把前驱的 next 指向待删节点的后继,必须先访问前驱(通常从头遍历),只知道待删节点地址无法完成删除。
在宽度优先搜索中,通常使用队列来辅助实现。
A:正确。BFS 按层扩展,需要先入队的结点先出队,队列的 FIFO 特性正好保证逐层顺序访问,是 BFS 的标准辅助结构。
哈夫曼编码的主要应用领域是有损数据压缩。
B:错误。哈夫曼编码生成前缀码,解码能无损还原原文,主要应用于无损数据压缩(如文件压缩);有损压缩会丢失信息,如 JPEG,与哈夫曼无关。
二叉搜索树的查找操作的时间复杂度是 。
B:错误。BST 查找平均时间复杂度为 O(log N),仅当树退化成链时最坏才达 O(N),笼统说查找是 O(N) 不准确。
栈的基本操作包括入栈(push)和出栈(pop)。
A:正确。栈是后进先出(LIFO)结构,push 在栈顶压入元素、pop 弹出栈顶元素,入栈与出栈是栈的两个基本操作,其余如取栈顶都是辅助操作。
使用哈夫曼编码对一些字符进行编码,如果两个字符的频率差异最大,则它们的编码可能出现相同的前缀。
B:错误。哈夫曼编码是前缀码,任意两个字符的编码都互不为对方前缀,这是前缀码的定义性质,与频率差异大小无关,频率差异最大的两个字符也不例外。