华为员工爆料:晚上,突然接到领导的电话,问我愿不愿意到非洲上班,工资45000元,5年,双倍年终奖....

科技   2024-11-17 12:59   山西  

最近看到一个有意思的爆料,不禁想和大家聊聊这个话题。一个华为员工突然接到领导的电话,问他愿不愿意去非洲上班,工资45000元,合同五年,外加双倍年终奖。

但这位同事也不傻,问了一句:“为什么选我?” 领导的回答更让人“惊呆”了:“你不是准备买房吗?五年赚够一套房,心动不?”

大家都知道,程序员虽然在国内有不小的工资,但买房的压力也大得很。要是换到非洲,换个环境,薪水翻倍,生活成本可能还低,那么这是不是个机会呢?

我觉得,在这种情况下,关键是看两个因素:薪水的吸引力个人的生活需求

如果合同靠谱,薪水按时到位,我觉得不妨去试试看,也许这是一个能改变人生轨迹的机会。毕竟,钱难赚,但机会一旦错过,可能就没了。

怎么样,你们觉得呢?

算法题:不同的子序列

聊一个经典的算法问题:不同的子序列看似简单,其实背后涉及了动态规划的深度和对边界条件的严密把控。
为了避免直接暴力破解问题,我会给你一些思路。我们不仅要在求解子序列的数量时快速高效,还要保证它的准确性和时间复杂度。
首先,我们得理解什么是子序列。子序列就是从原始字符串中删除某些字符(但不改变剩下字符的顺序)得到的字符串。例如,字符串 "abc" 的子序列有:""(空串)、"a"、"b"、"c"、"ab"、"ac"、"bc" 和 "abc"。
问题是,如何求得一个给定字符串所有不同的子序列数目呢?这里的关键点在于如何避免重复。我们可以考虑字符串中某些字符重复的情况,比如字符串 "aba" 中的子序列 "a" 就会被计算两次。所以我们需要一些技巧来解决这个问题。
接下来,我们将用动态规划来解决这个问题。简单来说,我们需要用一个数组来记录到目前为止每一个位置上所能生成的不同子序列的数量。
动态规划的状态转移
假设我们有一个字符串 s,长度为 n,我们用一个数组 dp 来存储到第 i 个字符时能够形成的子序列个数。初始时,dp[0] = 1,表示空字符串的子序列只有一个,就是空串。
对于每个字符 s[i],我们考虑它能新增多少个子序列。如果 s[i] 没有重复出现,那么新增的子序列就是当前子序列数的两倍。原因很简单:我们可以将 s[i] 加入之前的所有子序列中,形成新的子序列。
但问题是,如果 s[i] 在之前的某个位置也出现过,那么我们新增的子序列会有重复的情况。所以,我们需要记录之前 s[i] 出现的位置,以避免重复计数。
代码实现
import java.util.HashMap;

public class DistinctSubsequences {
    public int distinctSubseqII(String s) {
        int mod = 1000000007;
        int n = s.length();
        long[] dp = new long[n + 1];
        HashMap<Character, Integer> lastIndex = new HashMap<>();
        dp[0] = 1// 空串的子序列数是1

        for (int i = 1; i <= n; i++) {
            // dp[i] 是 dp[i-1] 的两倍,表示当前字符可以在所有子序列后面加上
            dp[i] = dp[i - 1] * 2 % mod;

            // 如果当前字符之前出现过,去掉重复的部分
            if (lastIndex.containsKey(s.charAt(i - 1))) {
                int last = lastIndex.get(s.charAt(i - 1));
                dp[i] = (dp[i] - dp[last - 1] + mod) % mod;
            }

            // 更新当前字符的最后出现位置
            lastIndex.put(s.charAt(i - 1), i);
        }

        // 最后返回 dp[n] - 1, 1 是因为我们不考虑空子序列
        return (int) (dp[n] - 1);
    }

    public static void main(String[] args) {
        DistinctSubsequences solution = new DistinctSubsequences();
        String s = "aba";
        System.out.println(solution.distinctSubseqII(s)); // 输出 6
    }
}
分析
  1. dp[i] 表示考虑到字符串的前 i 个字符,能组成多少个不同的子序列。
  2. 对于每一个 s[i],我们用 dp[i] = dp[i - 1] * 2 来计算,因为它可以出现在之前所有子序列的末尾。
  3. 如果字符 s[i] 在之前出现过,我们就减去重复的子序列。这里通过一个哈希表 lastIndex 来记录每个字符最后一次出现的位置,避免重复计算。
  4. 最后返回 dp[n] - 1,因为我们不计空子序列。
这道题目考察了动态规划的技巧,尤其是如何处理重复元素。通过哈希表记录每个字符最后出现的位置,我们能在 O(1) 的时间内处理重复子序列的情况,避免暴力遍历所有子序列的超时问题。
总结
  • 这个问题的核心思想是动态规划,通过状态转移来计算不同子序列的个数。
  • 我们通过哈希表来避免重复的计算,以此降低了时间复杂度。
  • 最后,我们的时间复杂度是 O(n),空间复杂度也是 O(n),相较于暴力枚举所有子序列的 O(2^n),这简直就是一场大胜。
下次遇到类似的题,记得灵活应用动态规划+哈希表的组合哦。
对编程、职场感兴趣的同学,可以链接我,微信:coder301 拉你进入“程序员交流群”。
🔥东哥私藏精品 热门推荐🔥

东哥作为一名超级老码农,整理了全网最全《Java高级架构师资料合集》

资料包含了《IDEA视频教程》《最全Java面试题库》、最全项目实战源码及视频》及《毕业设计系统源码》总量高达 650GB 。全部免费领取!全面满足各个阶段程序员的学习需求。

Java面试那些事儿
回复 java ,领取Java面试题。分享AI编程,Java教程,Java面试辅导,Java编程视频,Java下载,Java技术栈,AI工具,Java开源项目,Java简历模板,Java招聘,Java实战,Java面试经验,IDEA教程。
 最新文章