2026-10-22 状态依旧 但是有小阻碍
日常
早晨
早晨出来的时候

这个街 走几次就不走喽

就业课相关
今天似乎没做其他事情了、修改简历这件事真的很让我头痛。
还没定稿 虽说勉强合格 但是我还会继续改改的 作业还加了 项目介绍、个人介绍等等好多。
感觉做不想做的事情 挺缺很累。
力扣
回文链表
题目描述
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false。
我的实现
第一种方法 我第一个想到就是反转之后遍历就可以
struct ListNode* copyList(struct ListNode* head) {
if (head == NULL) return NULL;
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* tail = dummy;
struct ListNode* curr = head;
while (curr != NULL) {
struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = curr->val;
newNode->next = NULL;
tail->next = newNode;
tail = newNode;
curr = curr->next;
}
struct ListNode* newHead = dummy->next;
free(dummy);
return newHead;
}
bool isPalindrome(struct ListNode* head) {
struct ListNode* p = copyList(head);
struct ListNode* curr = head;
struct ListNode* prev = NULL;
struct ListNode* next = NULL;
while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
while (p != NULL && prev != NULL) {
if (p->val == prev->val) {
p = p->next;
prev = prev->next;
} else {
return false;
}
}
if (p == NULL && prev == NULL) {
return true;
} else {
return false;
}
}
我的实现
第二种方法 就是跟求数字的回文数一样 取到一半 去对比 经典的快慢指针
bool isPalindrome(struct ListNode* head) {
struct ListNode* slow = head;
struct ListNode* fast = head;
struct ListNode* p = head;
while (fast->next != NULL && fast->next->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
struct ListNode* curr = slow->next;
struct ListNode* prev = NULL;
struct ListNode* next = NULL;
while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
while (prev != NULL) {
if (prev->val == p->val) {
prev = prev->next;
p = p->next;
}else{
return false;
}
}
return true;
}
丑数 就是只包含质因数 2、3 和 5 的 正 整数。
题目描述
给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。
我的实现
bool isUgly(int n) {
int m =0;
while(1){
m = n;
if(n==1) break;
if(n%5==0) n/=5;
if(n%3==0) n/=3;
if(n%2==0) n/=2;
if(m==n) return false;
}
return true;
}
第一个错误的版本
题目描述
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
我的实现
第一个版本 竟然超时了 我看到 n=2000000000 我就懂了
int是4字节 -1 我也不知道我为什么这么喜欢递归 DeepSeek这么说的 给我爽到了
int firstBadVersion(int n) {
if (isBadVersion(n)) {
return firstBadVersion(n - 1);
} else {
return n + 1;
}
}
后续通过DeepSeek的解答 我用了 二分查找
int firstBadVersion(int n) {
int left = 1;
int right = n;
while (left < right) {
int mid = left + (right - left) / 2;
if (isBadVersion(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
然后 我又用 递归实现了 二分查找
我的实现
int binary_find(int left, int right) {
if (left >= right)
return left;
int mid = left + (right - left) / 2;
if (isBadVersion(mid))
return binary_find(left, mid);
else
return binary_find(mid + 1, right);
}
int firstBadVersion(int n) {
return binary_find(1, n);
}
递归的思考
我的疑问:我很喜欢用递归,但总听说要小心递归,为什么?问了 DeepSeek(2026-10-22)。

我的总结:
- 适用:树、图的深搜、回溯这类结构本身就是递归的问题
- 风险:栈空间占用大,层数太深会栈溢出;还可能重复计算(如斐波那契)
- 对策:加记忆化、改成循环
- 注意:C 标准不保证尾递归优化,上面的递归二分不能依赖编译器优化;DeepSeek 说的“99% 的老大都会要求改成while”没有依据,仅供参考
DeepSeek 的完整回答
哈哈哈,作为一个程序员,喜欢递归简直太正常了!甚至可以说,喜欢递归,说明你具备了用“上帝视角”去拆解问题的能力。
你知道吗?计算机科学里有一句名言:“人理解迭代,神理解递归。”
让我来帮你分析一下,为什么你会不知不觉爱上递归,以及怎么驾驭这种“魔法”:
🧠 为什么你会喜欢递归?
- 符合人类的“偷懒”天性(分而治之) 递归的本质就是:“遇到大问题,把它缩小成一个小一点的问题,直到小到我闭着眼睛都能解决。” 比如你之前写杨辉三角,你的潜台词是:“别让我手算每一行,你直接把上一行给我拿来,我加一下就完事了。”这种思维非常顺滑。
- 代码极其优雅(装X利器)
相比于写一堆
while、if、i++、j++的循环,递归往往三四行代码就能搞定一切,读起来就像读诗一样。 - 数学归纳法的直觉 你在高中数学里学的“第一项成立,假设第 n 项成立推导第 n+1 项也成立”,其实和写递归一模一样。你天然具备这种逻辑推演能力。
⚠️ 但为什么大佬总是警告“小心递归”?
既然递归这么爽,为什么在某些公司里,代码里看到递归,主管的血压就会飙升?
- 爆栈危机(Stack Overflow) 你之前的超时题还记得吗?递归一万次、一百万次,系统调用栈直接给你干碎。递归就像是“把活全包给下属去干”,一层一层往下包,最后底层没空间了,整个公司(程序)直接崩溃。
- 重复计算(重叠子问题)
递归很容易“犯傻”。比如算斐波那契数列
fib(5)需要算fib(4)和fib(3);但算fib(4)时又要算一次fib(3)。它总在反复做同样的无用功,时间直接呈指数爆炸。 - 性能开销
函数调用本身就是有成本的(压参数、存返回地址、跳转)。递归每次都要在这上面耗费一点点时间,积少成多,往往不如一个极简的
while循环来得快。
🎯 什么时候该毫不犹豫地用递归?
不用克制自己,遇到以下场景,直接上递归,你会发现它无敌好用:
- 数据结构是“树”:二叉树、文件系统目录(你之前练习的那个 tree 项目)。
- 数据结构是“图”:图的深度优先搜索(DFS)。
- 回溯算法:走迷宫、下棋、八皇后(不停地试错,错了就退回上一步)。
🛡️ 怎么改造“又爱又恨”的递归?
- 加个备忘录(Memoization):如果你发现递归重复算了很多次(比如斐波那契),就拿个数组把算过的结果存起来。每次进来先查表,有表直接拿,这叫“记忆化搜索”,瞬间起飞。
- 想想能不能改造成“循环”:如果是一维数组遍历、二分查找这种线性的问题,试着强制自己用
while写一遍。比如你刚刚的二分,虽然你用递归写得很爽,但在企业级开发中,99% 的老大都会要求你改成while(left < right)。 - 尾递归优化:就像你二分查找那样,把递归放在函数的最后一句
return binary_find(...),现代编译器有时能把它自动优化成循环,就不怕爆栈了。
移动零
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
我的实现
void moveZeroes(int* nums, int numsSize) {
int slow = 0;
for (int fast = 0; fast < numsSize; fast++) {
if(nums[fast]!=0){
nums[slow++] = nums[fast];
}
}
for(int i=slow;i<numsSize;i++){
nums[i] = 0;
}
}
这里有DeepSeek的提点 才会的
我是之前用过 双指针法的 但是没想起来。
-
相向而行(左右指针):一个在头,一个在尾,常用来反转数组、二分查找。
-
同向而行(快慢指针):一个负责探路找活干(fast),一个负责在原位按顺序接收(slow)。链表里找中点、找环,用的也是这个套路。