裸睡,一觉醒来发现隔壁躺着hr,尴尬~

文摘   2024-11-19 12:21   山西  
一场堪比“社死巅峰”的意外,主角是一位去上海秋招的兄弟,咱就是说,这种事要是轮到我,直接原地Ctrl+Alt+Del重启人生了。
事情是这样的,这哥们入住酒店时,前台小姐姐告诉他:“今晚你一个人住,另一位明天才到。”于是,这位老铁大脑一热:那不就自由了吗?内裤、袜子直接甩另一张床,光溜溜一头扎进梦乡,毫无心理负担😌。

半夜,电话响了一下,他迷迷糊糊没接,翻了个身继续睡。这一睡,就是天亮。等到天亮的时候,他打了个哈欠睁眼一看,差点当场蓝屏——隔壁床上多了个人!
仔细一瞅,这位“同学不仅出现得悄无声息,还把他的内裤和袜子摆到了桌上!这细心劲儿,绝了。
尴尬得满头是汗,他心想,大概率是同去秋招的同学吧?赶紧打个招呼,结果一问,天雷滚滚:对方竟然是——HR!
但话说回来,下次出门,咱们先确认房间真的没别人,再放飞自我吧!😂

算法题:俄罗斯套娃信封问题


咱们来聊一个在算法面试中挺常见的题:俄罗斯套娃信封问题。别被这个名字吓到,其实就是一组信封,你得找出其中可以相互套住的最多个数。说白了,这不就是程序员版的“谁套得过谁”嘛?😂
问题是这样的:给你一堆信封,每个信封有宽度和高度两个参数。规则是一个信封能装进另一个信封的条件是它的宽度和高度都比另一个信封小。你需要返回最多能套的信封数量。
这问题有点像二维版的最长递增子序列 (LIS)。听到LIS,是不是很多人已经头疼了?别怕,我给大家捋捋。
思路分析
  1. 先排序
    我们先按信封的宽度从小到大排序,如果宽度相同,就按高度从大到小排。这一步很关键,因为这样可以防止宽度相同时,错误地将高度也按递增算进去。
    比如信封 [5,4], [5,2],如果不把高度按降序排,两个 [5, _] 会互相干扰。
    排序后就是这样:
    输入:[ [5,4], [6,4], [6,7], [2,3] ]
    排序:[ [2,3], [5,4], [6,7], [6,4] ]
  2. 转化为LIS问题
    现在只需要在排好序的信封高度中找最长递增子序列。因为宽度已经保证不会干扰了,问题就变成一维的了,简单多了。
代码实现
来吧,上代码:
import java.util.Arrays;

public class RussianDollEnvelopes {
    public int maxEnvelopes(int[][] envelopes) {
        // 按宽度升序,如果宽度相同则按高度降序
        Arrays.sort(envelopes, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);

        // 提取高度数组
        int[] heights = new int[envelopes.length];
        for (int i = 0; i < envelopes.length; i++) {
            heights[i] = envelopes[i][1];
        }

        // 找高度数组的最长递增子序列
        return lengthOfLIS(heights);
    }

    private int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        int len = 0;

        for (int num : nums) {
            // 二分查找插入点
            int index = Arrays.binarySearch(dp, 0, len, num);
            if (index < 0) index = -(index + 1);  // 转换为插入点
            dp[index] = num;
            if (index == len) len++;  // 如果插入在最后,说明序列长度增加
        }

        return len;
    }

    public static void main(String[] args) {
        RussianDollEnvelopes solver = new RussianDollEnvelopes();
        int[][] envelopes = {{5,4}, {6,4}, {6,7}, {2,3}};
        System.out.println("最多能套的信封数量是: " + solver.maxEnvelopes(envelopes));
    }
}
代码讲解
  1. 排序的 Arrays.sort 用了自定义 Comparator,先比宽度,再比高度。
  2. lengthOfLIS 方法里用了动态规划+二分查找。每次在当前的递增子序列中找插入点。如果找不到合适位置就扩展序列。
  • Arrays.binarySearch 负责查找插入点,效率是 O(log n)
  • 最后 dp 数组长度就是最长递增子序列的长度。
整体复杂度是 O(n log n),很香吧?🍕面试官看到这,肯定对你刮目相看。
这题其实挺适合用来刷算法思路的,因为它考察了排序和动态规划的结合,还得对二分查找熟悉。不熟?没关系,多练练就好。
最后,这题的核心思路还是在于转化问题。你看,二维的问题转成一维后,一切都变简单了。这和写代码一样,有时候绕一绕,说不定还能发现更优解。

-END-


ok,今天先说到这,老规矩,给大家分享一份不错的副业资料,感兴趣的同学找我领取。

以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言

程序媛山楂
5年+程序媛,专注于AI编程普及。本号主要分享AI编程、Chat账号、Chat教程、Sora教程、Suno AI、Sora账号、Sora提示词、AI换脸、AI绘画等,帮助解决各种AI疑难杂症。
 最新文章