小米汽车值得去吗?最终拒了 offer。

车企选择

今天逛某职场 App 时,无意间看到一篇寻求 offer 抉择意见的帖子:

alt

这位同学刚从加班闻名(但 CEO 强调既学华为狼性,也学华为分配)的理想汽车离职。

经过了 6 轮面试,收到了小米 offer,但目前纠结是否要去。

不好的地方,入职前面试官就明说了,基本上每天都 10 点后下班,而且候选人也担心小米汽车不靠谱。

好的地方,待遇给的是真心不错。

连从理想汽车跳槽出来的网友都觉得不错,那说明小米汽车的待遇确实是有竞争力的。

但评论区有不少小米员工则现身说法,表达的都是「劝退」意见:

alt
alt

有同学强调,实际情况下班都是晚上 10:30 起步,而且入职时宣称的弹性工作时间,只弹了下班时间 🤣

alt
alt

还有同学指出,小米内卷严重,期权不合理,而且小米汽车只是试水产品,会有失败风险。

最终,这位同学"听劝"了,决定放弃小米 offer,入职大众中国。

alt

但这些都是网友在去年 10 月给出的意见了,现在小米汽车上市交付已经有段时间,基本上是空前成功,热度不减,一车难求。

按照常规理解,小米汽车的年终奖应该不会低,也不知道那位楼主有没有拍断大腿。

...

回归主线。

来一道和「新能源车企」相关的算法原题。

题目描述

平台:LeetCode

题号:1775

给你两个长度可能不等的整数数组 nums1 和 nums2 。两个数组中的所有值都在 1 到 6 之间(包含 1 和 6)。

每次操作中,你可以选择 任意 数组中的任意一个整数,将它变成 1 到 6 之间 任意 的值(包含 1 和 6)。

请你返回使 nums1 中所有数的和与 nums2 中所有数的和相等的最少操作次数。如果无法使两个数组的和相等,请返回 -1 。

示例 1:

输入:nums1 = [1,2,3,4,5,6], nums2 = [1,1,2,2,2,2]

输出:3

解释:你可以通过 3 次操作使 nums1 中所有数的和与 nums2 中所有数的和相等。以下数组下标都从 0 开始。
- 将 nums2[0] 变为 6 。 nums1 = [1,2,3,4,5,6], nums2 = [6,1,2,2,2,2] 。
- 将 nums1[5] 变为 1 。 nums1 = [1,2,3,4,5,1], nums2 = [6,1,2,2,2,2] 。
- 将 nums1[2] 变为 2 。 nums1 = [1,2,2,4,5,1], nums2 = [6,1,2,2,2,2] 。

示例 2:

输入:nums1 = [1,1,1,1,1,1,1], nums2 = [6]

输出:-1

解释:没有办法减少 nums1 的和或者增加 nums2 的和使二者相等。

示例 3:

输入:nums1 = [6,6], nums2 = [1]

输出:3

解释:你可以通过 3 次操作使 nums1 中所有数的和与 nums2 中所有数的和相等。以下数组下标都从 0 开始。
- 将 nums1[0] 变为 2 。 nums1 = [2,6], nums2 = [1] 。
- 将 nums1[1] 变为 2 。 nums1 = [2,2], nums2 = [1] 。
- 将 nums2[0] 变为 4 。 nums1 = [2,2], nums2 = [4] 。

提示:

枚举 + 贪心 + 数学

nums1 的长度为 nnums2 的长度为 m,根据题意两数组的值域分别为 ,可分别视为数轴上的两条线段。

为了方便,我们人为固定 ,若不满足则交换两数组,返回 minOperations(nums2, nums1) 即可。

先来考虑无解的情况:当 时,说明两线段不重合,必然无法通过变换使得总和相等,直接返回 -1

由于 的范围为 ,且 的值域大小 ,因此我们可以通过枚举最终目标和 x(两线段的重合部分)来做,枚举范围不超过

于是问题转换为:对于一个原总和为 sum 的数组 nums 而言,按照题目的变换规则,至少经过多少次变换,才能将其总和变为 x

根据原总和 sum 和目标结果 x 的大小关系进行分情况讨论(将两者差值绝对值记为 d):

  • 时,对于原数为 的数而言,其能变为不超过 的任意数。

    例如 能够变化为 中的任意数,即单个数值 最多能够抵消 个差值,不失一般性的可概括为原数为 所能抵消的差值为

    因此,我们贪心的使用较大数进行变换(从 枚举 i),对于每个数值 i 而言,其所能提供的个数为

  • 时,同理,原数为 所能提供的最大抵消数为 ,因此我们贪心使用较小数进行变换(从 枚举 i),对于每个数值 i 而言,其所能提供的个数为

如此一来,我们通过枚举两线段重合点 x,复杂度为 ,并通过复杂度为 的数学方法来得知将两原数组总和变为 x 所需要的操作次数 cnt,在所有的 cnt 取最小值即是答案。整体计算量为 ,可以过。

Java 代码:

class Solution {
    int[] c1 = new int[10], c2 = new int[10];
    int s1, s2;
    public int minOperations(int[] nums1, int[] nums2) {
        int n = nums1.length, m = nums2.length;
        if (n > m) return minOperations(nums2, nums1);
        if (m > 6 * n) return -1;
        for (int x : nums1) {
            c1[x]++; s1 += x;
        }
        for (int x : nums2) {
            c2[x]++; s2 += x;
        }
        int ans = n + m;
        for (int i = m; i <= 6 * n; i++) ans = Math.min(ans, getCnt(c1, s1, i) + getCnt(c2, s2, i));
        return ans;
    }
    int getCnt(int[] cnts, int sum, int x) {
        int ans = 0;
        if (sum > x) {
            for (int i = 6, d = sum - x; i >= 2 && d > 0; i--) {
                int c = Math.min((int) Math.ceil(d * 1.0 / (i - 1)), cnts[i]);
                ans += c; d -= c * (i - 1);
            }
        } else if (sum < x) {
            for (int i = 1, d = x - sum; i <= 5 && d > 0; i++) {
                int c = Math.min((int) Math.ceil(d * 1.0 / (6 - i)), cnts[i]);
                ans += c; d -= c * (6 - i);
            }
        }
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    int c1[10], c2[10];
    int s1, s2;
    int minOperations(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size(), m = nums2.size();
        if (n > m) return minOperations(nums2, nums1);
        if (m > 6 * n) return -1;
        for (int x : nums1) {
            c1[x]++; s1 += x;
        }
        for (int x : nums2) {
            c2[x]++; s2 += x;
        }
        int ans = n + m;
        for (int i = m; i <= 6 * n; i++) {
            ans = min(ans, getCnt(c1, s1, i) + getCnt(c2, s2, i));
        }
        return ans;
    }
    int getCnt(int cnts[], int sum, int x) {
        int ans = 0;
        if (sum > x) {
            for (int i = 6, d = sum - x; i >= 2 && d > 0; i--) {
                int c = min((intceil(d * 1.0 / (i - 1)), cnts[i]);
                ans += c; d -= c * (i - 1);
            }
        } else if (sum < x) {
            for (int i = 1, d = x - sum; i <= 5 && d > 0; i++) {
                int c = min((intceil(d * 1.0 / (6 - i)), cnts[i]);
                ans += c; d -= c * (6 - i);
            }
        }
        return ans;
    }
};

Python 代码:

class Solution:
    def minOperations(self, nums1: List[int], nums2: List[int]) -> int:
        n, m = len(nums1), len(nums2)
        if n > m:
            return self.minOperations(nums2, nums1)
        if m > 6 * n:
            return -1
        c1, c2 = Counter(nums1), Counter(nums2)
        s1, s2 = sum(nums1), sum(nums2)
        def getCnt(cnts, tot, x):
            ans = 0
            if tot > x:
                d = tot - x
                for i in range(61-1):
                    if d <= 0:
                        break
                    c = min(math.ceil(d / (i - 1)), cnts[i])
                    ans, d = ans + c, d - c * (i - 1)
            elif tot < x:
                d = x - tot
                for i in range(16):
                    if d <= 0:
                        break
                    c = min(math.ceil(d / (6 - i)), cnts[i])
                    ans, d = ans + c, d - c * (6 - i)
            return ans
        ans = n + m
        for i in range(m, 6 * n + 1):
            ans = min(ans, getCnt(c1, s1, i) + getCnt(c2, s2, i))
        return ans
  • 时间复杂度: ,其中 的值域大小
  • 空间复杂度:

最后

给大伙通知一下 📢 :

全网最低价 LeetCode 会员目前仍可用!!!

📅 年度会员:有效期加赠两个月!!; 季度会员:有效期加赠两周!!

🧧 年度会员:获 66.66 现金红包!!; 季度会员:获 22.22 现金红包!!

🎁 年度会员:参与当月丰厚专属实物抽奖(中奖率 > 30%)!!

专属链接:leetcode.cn/premium/?promoChannel=acoier

我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻。

欢迎关注,明天见。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值