学习项目中踩的坑和注意点

有的项目课程是2020年左右的,当时使用的boost 1.69和gcc 4.6版本,放到现在(2025年)的Ubuntu 24版本下,不能很好地兼容。
此时为了尽快顺利进入到课程学习的轨道上,而不是为了想办法去兼容新Ubuntu,妥协的做法是安装一个降级的Ubuntu 20版本。

记录安装muduo过程的配套工具的版本

以下环境能成功安装muduo老版本

  1. Ubuntu 20.04.6
  2. gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
  3. g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
  4. cmake version 3.16.3
  5. make: GNU Make 4.2.1 Built for x86_64-pc-linux-gnu

以上,都是Ubuntu此版本apt安装的默认的版本。

Ubuntu的跨虚拟机复制粘贴问题

VMware虚拟机Linux与主机Windows之间不能拖拽、跨端复制粘贴

验证VMware Tools安装状态

1
2
3
4
5
6
# 检查VMware服务状态
sudo systemctl status vmware-tools

# 确认open-vm-tools已安装
sudo apt list --installed | grep open-vm-tools # Debian/Ubuntu
rpm -qa | grep open-vm-tools # CentOS/RHEL

重启关键服务

1
2
sudo systemctl restart vmware-tools
sudo systemctl restart vmtoolsd

如果vmware-tools.service could not be found

安装/重装 open-vm-tools

1
2
3
4
5
6
7
8
9
# Ubuntu/Debian
sudo apt update
sudo apt install --reinstall open-vm-tools open-vm-tools-desktop

# CentOS/RHEL
sudo yum reinstall open-vm-tools open-vm-tools-desktop

# 启用服务(服务名是 vmtoolsd)
sudo systemctl enable --now vmtoolsd

检查驱动加载状态

1
2
3
4
lsmod | grep -E 'vmw_vmci|vmw_vsock_vmci_transport'
# 应有类似输出:
# vmw_vmci 98304 1
# vmw_vsock_vmci_transport 45056 0

强制重装工具

1
2
sudo apt purge open-vm-tools && sudo apt autoremove
sudo apt install open-vm-tools open-vm-tools-desktop

如果不稳定,建议使用挂载点共享文件

目前确实可以复制粘贴文本、小文件了,但是大文件不行,很不稳定。

虚拟机设置 → 选项 → 共享文件夹 → 添加主机目录

会挂载到Linux的/mnt/hgfs下。

01_数组_01_二分查找

https://leetcode.cn/problems/binary-search/

内容

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. nums 的每个元素都将在 [-9999, 9999]之间。

代码(线性探测重复值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
int search(vector<int>& nums, int target) {
int pos = -1;
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
int mid = ((right - left) >> 1) + left;
if (target < nums[mid])
{
right = mid - 1;
}
else if (target > nums[mid])
{
left = mid + 1;
}
else // ==
{
pos = mid;
while (pos > left && nums[pos - 1] == target)
{
--pos;
}
break;
}
}
return pos;
}
};

坑1

我第一次在线性向前探测重复值的时候写错了 while 的判断条件,不应该是pos > 0,而是pos > left

坑2

第一次写的时候,把>> 2右移运算符写成了大于号> 2,而且,不应该是>> 2,应该是>> 1右移1位,也就是对应着除以2。这是致命的错误。

但是测试用例居然全都通过了!这可能是因为我用到了线性探测,让算法实际以遍历的形式找到了正确答案…

心得

在做二分查找或者分治思想类的题目,最难、最重要的把握点是物理下标和逻辑下标的关系。
像这个题目中,leftrightmid都是物理下标。
物理下标应该实时更新。
不应该只出现逻辑下标。
就像线性探测时的 while 条件中判断pos > 0就是错误使用了逻辑下标去充当条件。应当是pos > left + 0,省略+ 0即为pos > left

优化代码(继续二分探测)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
int search(vector<int>& nums, int target) {
int pos = -1;
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
int mid = ((right - left) >> 1) + left;
if (target < nums[mid])
{
right = mid - 1;
}
else if (target > nums[mid])
{
left = mid + 1;
}
else // ==
{
pos = mid;
right = mid - 1;
}
}
return pos;
}
};

这能让探测行为继续保持二分的O(logn)O(\log {n})的复杂度进行。
O(logn+k)O(\log {n} + k)(k为重复次数)优化至 O(logn)O(\log {n}),完全消除了线性探测的开销。

总结