同事原来20K,跳槽去了一个月薪25K的,结果项目被叫停,组内全员裁撤!然后重新找工作,现在3个多月了还在家里。
是这样的:某位同事在原公司拿着20K的工资,突然跳槽去了一家公司,月薪一下子涨到了25K。听起来不错吧?薪水涨了,未来看起来也很美好。但没过多久,那个项目被叫停了,结果整个团队都被裁了。这可真是,猝不及防的打击。
更离谱的是,这位同事现在已经有三个月没找到新工作,依旧在家里。你说这事情是不是挺有意思的?😅
说实话,这也让我想到了跳槽时的风险。大家都知道,薪资涨得快也没什么不对,但跳槽之前要考虑清楚,不单单是眼前的工资,还要看公司稳定性、行业前景以及个人发展。
所以嘛,跳槽要谨慎,薪水虽高,但能不能稳住饭碗更重要。不然最终就成了“家里蹲”一族了【备注:文末可领最新资料】。
算法题:两个子序列的最大点积
今天又来跟大家聊聊一道有点“烧脑”的算法题。这题说实话,刚开始看觉得有点头疼,但只要理解了其中的思想,就能迎刃而解。好了,不废话,直接进入正题。
题目要求我们找到两个子序列的最大点积。先来复习一下“点积”这个概念。假设我们有两个向量,A = [a1, a2, ..., an] 和 B = [b1, b2, ..., bn],它们的点积就是对应元素相乘后的和,即:A · B = a1 * b1 + a2 * b2 + ... + an * bn
回到题目,我们的目标是找到两个子序列,它们的点积最大。首先,子序列的定义大家应该都清楚吧,就是从原序列中删除某些元素(可能一个也不删)而不改变其相对顺序,形成的新序列。
那么,问题来了,如何通过遍历所有的子序列来找到最大点积呢?那可不行!直接暴力解法的时间复杂度太高,能不能找到更高效的解法呢?
在思考这个问题时,我们可以借助动态规划来优化计算。核心思想是,假设我们有两个数组 A 和 B,我们可以通过动态规划(DP)来递归地求解每一对子序列的最大点积。
思路分析
我们定义一个二维 DP 数组 dp[i][j],表示从 A[i] 和 B[j] 开始,计算它们的最大点积。
状态转移方程的意思是:
如果我们选择 A[i]和B[j]作为当前的子序列元素,dp[i][j]就等于dp[i+1][j+1](即跳到下一个元素)加上A[i] * B[j]。如果我们不选择其中一个元素,就分别尝试选择下一个元素的情况,更新 dp[i][j]。
算法步骤
初始化 DP 数组: dp[i][j]表示从A[i]和B[j]开始,计算的最大点积。状态转移:对于每一对 (i, j),我们可以选择将A[i]和B[j]放入子序列中,或者跳过它们,最终返回最大值。边界条件:当我们遍历到 A或B的末尾时,返回 0。
代码实现
public class MaxDotProduct { public static int maxDotProduct(int[] A, int[] B) {
int m = A.length;
int n = B.length;
// 初始化 dp 数组,注意这里的 dp 数组大小是 (m+1) * (n+1)
int[][] dp = new int[m + 1][n + 1];
// 初始化 dp 数组,填充为最小值,用来辅助求最大值
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
dp[i][j] = Integer.MIN_VALUE;
}
}
// 递推公式填充 dp 数组
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
dp[i][j] = Math.max(dp[i + 1][j + 1] + A[i] * B[j], Math.max(dp[i + 1][j], dp[i][j + 1]));
}
}
// 最终返回 dp[0][0] 即为所求的最大点积
return dp[0][0];
}
public static void main(String[] args) {
int[] A = {1, 3, -5};
int[] B = {-2, 4, 1};
System.out.println("最大点积: " + maxDotProduct(A, B)); // 输出结果
}
}
代码解释
初始化:我们先定义了一个大小为
(m+1) * (n+1)的 DP 数组,m是A的长度,n是B的长度。我们给dp[i][j]赋初值为Integer.MIN_VALUE,目的是为了在后面的比较中找到最大值。状态转移:在计算
dp[i][j]时,考虑两种选择:
选择当前的 A[i]和B[j],那么点积就是A[i] * B[j]加上剩余部分的最大点积dp[i+1][j+1]。跳过当前的 A[i]或B[j],分别计算跳过后的最大点积。
最终答案:我们需要的答案就在 dp[0][0] 位置,它保存了从 A[0] 和 B[0] 开始的最大点积。
复杂度分析
时间复杂度: O(m * n),我们遍历了A和B的所有元素进行状态转移。空间复杂度: O(m * n),我们需要一个大小为(m+1) * (n+1)的 DP 数组来存储状态。
总结
通过动态规划,我们能够高效地求解这个问题,而不是通过暴力枚举所有子序列。其实,这道题的关键就是如何通过状态转移来减少冗余计算。程序员的世界里,最重要的就是要学会找到问题的本质,拿到“高效”的解决方案,这样才能让代码跑得更快、效率更高。
最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek
也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。
-END-
以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言。