首先,进入IT、金融等行业后,月薪过万可能是“最低标准”,但这仅限于一部分职位。并非所有人都能轻松达到这一收入水平,很多人仍面临着房贷、车贷等压力。而在其他行业,月薪五千、六千才是普遍现象,收入差距较大。
其次,聚会时的“升职加薪”话题常让人产生“高薪幻觉”。大部分人在社交场合中喜欢分享自己的高收入,而收入较低的人往往保持沉默,这使得我们误以为“月薪过万”几乎成为常态。
实际上,攀比心态只能带来焦虑,而非实际的提升。
最后,社交媒体上的“炫富”内容也加剧了这种错觉。很多视频展示的是精心编排过的生活,远离现实。而这些内容往往只显示成功的一面,忽略了背后的努力与付出。
因此,面对“月薪过万”的幻想,理应保持理性,脚踏实地提升自己的技能和心态,才能实现真正的职业成长与收入提升。
算法题:缺失的第一个正整数
现在我们来聊一聊一个算法题,题目简单但有点让人头疼:缺失的第一个正整数。这是一个典型的面试题,也常见于一些编程平台的练习题。
题目给的输入是一个无序的整数数组,你需要找到其中缺失的第一个正整数,注意这里的“缺失”指的是从1开始的最小正整数。
这个问题看似简单,实际上考察的内容比较多,主要包括数组的遍历、空间复杂度的优化以及如何利用已有数据结构来提高效率。
首先,来看看一个简单的例子:
输入:
[1, 2, 0]
输出:
3
再看一个复杂点的例子:
输入:
[3, 4, -1, 1]
输出:
2
大家会发现,这个问题有点迷惑,因为数组里可能有负数、零或者重复的数字,所以我们得处理一些特殊情况。
解题思路
常规的思路是遍历数组,找到最大值,然后找出从1开始到最大值之间缺失的数字。这个方法的时间复杂度是O(n^2),直接暴力破解显然不够高效,特别是当数组很大的时候。其实我们可以做到**O(n)的时间复杂度和O(1)**的空间复杂度。
关键点:位置映射
我们要利用数组本身来做一些巧妙的操作。观察到这样一个规律:数组的索引从0到n-1,而我们关心的是1到n之间的正整数。所以,我们可以将每个数字放到它应该在的位置上,比如数字1应该放在索引0的位置,数字2应该放在索引1的位置,依此类推。通过这种方式,我们可以在一次遍历中完成整个问题的求解。
具体步骤
忽略负数和大于数组长度的数字:因为我们只关心1到n之间的数字,其他的数字不需要考虑。 将每个数字放到正确的位置:遍历数组,对于每个数字,如果它在1到n之间并且没有放在它应该放的位置上,就交换它和应该放置它的数字交换位置。 找到第一个缺失的正整数:经过交换后,数组的第i个位置应该是数字i+1。如果不是,就说明i+1就是缺失的那个正整数。
代码实现
下面是用Java写的代码实现:
public class Solution {
public int firstMissingPositive(int[] nums) {
int n = nums.length;
// 1. 将所有无效数字(负数和大于n的数)设为n+1
for (int i = 0; i < n; i++) {
if (nums[i] <= 0 || nums[i] > n) {
nums[i] = n + 1;
}
}
// 2. 根据值将每个数字放到对应的位置
for (int i = 0; i < n; i++) {
int val = Math.abs(nums[i]);
if (val <= n) {
// 将 nums[val - 1] 设为负数,表示val出现过
if (nums[val - 1] > 0) {
nums[val - 1] = -nums[val - 1];
}
}
}
// 3. 寻找第一个没有被标记的数
for (int i = 0; i < n; i++) {
if (nums[i] > 0) {
return i + 1;
}
}
// 如果所有的数都在正确的位置上,缺失的就是n+1
return n + 1;
}
}
代码解析
初始化阶段:我们首先遍历一遍数组,剔除不必要的数字。任何负数和大于数组长度的数字都不可能是我们需要的正整数,因此我们将它们设为
n+1
。这一步是为了避免浪费空间处理不相关的数据。交换位置:接下来,我们遍历数组,如果遇到1到n之间的数字,就把它放到它应该在的位置上。具体来说,数字
x
应该放在索引x-1
的位置上。所以我们通过交换的方式,把每个数字放到它应该处的位置。这一过程保证了每个数字尽量处于它应有的“正确位置”,即数字1在索引0位置,数字2在索引1位置,依此类推。查缺补漏:经过上述两步处理后,若数组从头到尾的位置都已经满足条件,那么说明1到n之间的数字都在数组中,缺失的正整数就是
n+1
。如果存在某个位置的数字不是该位置应有的数字,那么就说明这个数字是我们缺失的第一个正整数。
为什么空间复杂度是O(1)
你可能会问,为什么这道题能做到O(1)的空间复杂度呢?答案就在于我们利用了数组本身来存储信息,没有使用额外的空间结构,比如哈希表或者集合。这种做法把空间复杂度降到了最低,只用数组本身的空间来处理问题。
总结
这道题虽然表面看起来很简单,但要真正高效地解决它,需要一定的技巧。通过巧妙的交换和位置映射,我们避免了额外的空间消耗,同时保持了O(n)的时间复杂度。
对编程、职场感兴趣的同学,可以链接我,微信:coder301 拉你进入“程序员交流群”。