程序员老鬼

离职证明上,公司给了负面信息该怎么办

离职证明不是公司吐槽员工的地方,写成“能力差”“不服从管理”这种,已经不是难看,是给自己埋雷。离职证明该写的就那几样:劳动关系存续时间、岗位、离职时间,顶多再写一句“双方劳动关系已解除”。

Image

真碰上公司夹带负面评价,先别急着吵,直接要求重开,留好原件、聊天记录、邮件。因为这东西一旦影响你找下家,已经不是面子问题,是可能侵犯名誉和就业权益。

谈不拢,就去劳动监察投诉,或者直接走仲裁。很多公司嘴硬,真让它重新出一份,动作比谁都快。

算法题:不含连续1的非负整数

接口压测一跑,数据一改成 10^9,服务直接飙满。

第一反应不是看代码,是看入参。题目叫:不含连续 1 的非负整数。给一个 n,统计 0 ≤ x ≤ n,有多少个二进制表示里没有 “11”。

很多人第一版都是暴力:

publicintfindIntegers(int n){
int count = 0;
for (int i = 0; i <= n; i++) {
if (!hasConsecutiveOne(i)) {
            count++;
        }
    }
return count;
}

privatebooleanhasConsecutiveOne(int num){
int prev = 0;
while (num > 0) {
int cur = num & 1;
if (cur == 1 && prev == 1) {
returntrue;
        }
        prev = cur;
        num >>= 1;
    }
returnfalse;
}

逻辑没问题,n 小一点还能跑。线上真给你个 10^9,这种 O(n log n) 基本就是等超时。

这类题我一般先盯两个点: 一是“二进制”; 二是“不能连续”。

这两个放一起,味道就很像斐波那契。

先别急着看 n,先算“长度为 k 的合法数有多少”

假设我们只考虑二进制长度为 k 的数(允许前导 0),有多少个不含连续 1?

定义:

  • f[k] = 长度为 k 的合法数量

推一下:

  • 如果最高位是 0,那后面随便接长度 k-1 的合法串 → f[k-1]
  • 如果最高位是 1,那第二位必须是 0,后面接长度 k-2 的合法串 → f[k-2]

所以:

f[k] = f[k-1] + f[k-2]

典型斐波那契。

初始化:

  • f[0] = 1
  • f[1] = 2  // 0, 1

代码先打出来:

int[] dp = newint[32];
dp[0] = 1;
dp[1] = 2;

for (int i = 2; i < 32; i++) {
    dp[i] = dp[i - 1] + dp[i - 2];
}

这里 32 是因为 int 最高 31 位有效位,多留一位保险。

真正关键:怎么控制 ≤ n

很多人卡在这里。

思路不是枚举所有长度,而是从高位往低位扫 n 的二进制。

举个例子,n = 13 二进制是:1101

从最高位开始:

  • 第一位是 1 那我们可以把这一位变成 0,后面随便填 3 位合法数 → dp[3]

  • 然后继续看下一位 如果当前位和上一位都是 1,直接 break,因为已经出现连续 1

完整代码如下:

publicintfindIntegers(int n){
int[] dp = newint[32];
    dp[0] = 1;
    dp[1] = 2;

for (int i = 2; i < 32; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }

int result = 0;
int prevBit = 0;

for (int i = 30; i >= 0; i--) {
if ((n & (1 << i)) != 0) {
            result += dp[i];

if (prevBit == 1) {
return result;
            }
            prevBit = 1;
        } else {
            prevBit = 0;
        }
    }

return result + 1;
}

有两个细节容易写错:

  1. 出现连续 1 时,不能再算后面,直接 return
  2. 最后要 +1,因为 n 本身如果合法要算进去

为什么能这么做?

核心逻辑其实是“按位贪心 + 组合计数”。

每当你在第 i 位遇到一个 1,你可以选择:

  • 把它变成 0,后面 i 位随便填合法串(dp[i])
  • 或者保持 1,继续往下检查

一旦发现 “11”,后面就不可能再合法,提前结束。

这题表面是二进制判断,真正考的是:

  • 状态转移建模能力
  • 从“枚举数”转成“枚举位”
  • 把 ≤n 的限制转成前缀控制

很多人看到这种题第一反应是回溯,我一般看到“不能连续”就会条件反射去想 Fibonacci 结构。

算法题做久了,其实不是记答案,是对某些结构敏感。

这道题本质就是:二进制上的斐波那契 + 前缀限制剪枝。

能想到这一层,代码反而是最简单的部分。