美团开奖,真的很惊喜。

美团

美团开奖了。

作为一直以来被网友戏称的"开水团"(开水随便喝,别的福利没有),这次还真挺惊喜。

不少坐标北京的同学,都拿到了接近 SP 档位的 Offer:

alt

跟过我们开奖系列的读者都知道,今年很多白菜价是 1 字头的大厂,美团与他们相比,简直是神仙大厂。

我这里也收集了「北京美团-研发岗」今年的开奖情况:

  • 白菜:23k,15.5薪,年包 35w+
  • SP:25k~26k,15.5薪,5W 签字费(部分会有),年包 38w+(不含签字费)
  • SSP:28k~32k,15.5薪,8W 签字费,30w 股票(四年期),年包 46W+(不含签字费、股票)

今年美团,不仅仅是对标外面大厂很有诚意,即使是和去年相比,也少有涨幅(每个档位普遍涨了 1k~2k)。

而且更加整活的是,美团还试图摆脱"开水厂"的称号,开始考虑给内部员工福利上新了 🤣

就在本周,美团给内部员工上线了两项"重磅"福利:

  1. 推出 5 折员工单车骑行卡,员工员工骑小单车直接五折
  2. 员工每个月只需要花费 1 块钱就可领取价值 100 元的"神会员"省钱包

好家伙,开始往水里加白砂糖了,是吧?

团子,咱要不还是往「涨 base」的方向再出点力?

...

回归主题。

来一道和「校招」相关的算法题。

题目描述

平台:LeetCode

题号:1486

给你两个整数,nstart

数组 nums 定义为:nums[i] = start + 2 * i(下标从 0 开始)且 n = nums.length

请返回 nums 中所有元素按位异或(XOR)后得到的结果。

示例 1:

输入:n = 5, start = 0

输出:8

解释:数组 nums 为 [0, 2, 4, 6, 8],其中 (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8 。
     "^" 为按位异或 XOR 运算符。

示例 2:

输入:n = 4, start = 3

输出:8

解释:数组 nums 为 [3, 5, 7, 9],其中 (3 ^ 5 ^ 7 ^ 9) = 8.

示例 3:

输入:n = 1, start = 7

输出:7

示例 4:

输入:n = 10, start = 5

输出:2

提示:

模拟

数据范围只有 ,按照题目要求从头模拟一遍即可。

Java 代码:

class Solution {
    public int xorOperation(int n, int start) {
        int ans = start;
        for (int i = 1; i < n; i++) {
            int x = start + 2 * i;
            ans ^= x;
        }
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    int xorOperation(int n, int start) {
        int ans = start;
        for (int i = 1; i < n; ++i) {
            int x = start + 2 * i;
            ans ^= x;
        }
        return ans;
    }
};

Python 代码:

class Solution:
    def xorOperation(self, n: int, start: int) -> int:
        ans = start
        for i in range(1, n):
            x = start + 2 * i
            ans ^= x
        return ans

TypeScript 代码:

function xorOperation(n: number, start: number): number {
    let ans = start;
    for (let i = 1; i < n; i++) {
        let x = start + 2 * i;
        ans ^= x;
    }
    return ans;
};
  • 时间复杂度:
  • 空间复杂度:

数学

上述解法数据范围出到 大概率会发生 TLE。

如果数据范围出到 的话,本题难度应该会归为「中等」或「困难」。

事实上,本题存在「数学规律」解法。

原式子为

我们发现原式子中只有数值 是固定系数(由题目给定),考虑将其进行提出。

得到新式子 ,其中

之所以进行这样的转换操作,是因为我们想要利用 的异或性质。

「但是转换到了这一步,我们发现「新式子」与「原式子」其实并不相等。」

我们需要考虑两者之间的差值关系:

「不难发现,将「原式」转化成「新式」的集体除以 的操作相当于将每个 的进行「右移一位」,同时「异或运算」是每位独立计算的,因此「右移一位」不会影响移动部分的计算结果。」

「本质上,「原式」转化成「新式」是将最终答案 ans 进了「右移」一位的操作。因此如果要重新得到 ans,我们需要将其重新「左移」一位,将最后一位异或结果补回。」

原式结果 = 新式结果 << 1 | e 为最后一位异或结果(只能是 或者 ,其余高位为 )。

我们重新观察「原式」发现式子中每个 奇偶性相同,这意味着其二进制的最低位相同。

根据 nstart 的奇偶数搭配,不难得最后一位 e = n & start & 1

剩下的问题在于如何在不遍历的情况下计算「新式」结果,前面说到转化的目的是为了利用 异或特性。

事实上,这个式子存在一般性的推广结论:

因此只需要对最后一项进行 %4 讨论即可,这部分属于「结论」,详见代码的 calc 部分。

「总结一下,假设我们最终的答案为 ans。整个处理过程其实就是把原式中的每个 右移一位(除以 ),计算 ans 中除了最低一位以外的结果;然后再将 ans 进行一位左移(重新乘以 ),将原本丢失的最后一位结果重新补上。补上则是利用了 nstart 的「奇偶性」的讨论。」

Java 代码:

class Solution {
    int calc(int x) {
        if (x % 4 == 0return x;
        else if (x % 4 == 1return 1;
        else if (x % 4 == 2return x + 1;
        else return 0;
    }
    public int xorOperation(int n, int start) {
        // 整体除以 2,利用 %4 结论计算 ans 中除「最低一位」的结果
        int s = start >> 1;
        int prefix = calc(s - 1) ^ calc(s + n - 1);
        // 利用「奇偶性」计算 ans 中的「最低一位」结果
        int last = n & start & 1;
        int ans = prefix << 1 | last;
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    int calc(int x) {
        if (x % 4 == 0return x;
        else if (x % 4 == 1return 1;
        else if (x % 4 == 2return x + 1;
        else return 0;
    }
    int xorOperation(int n, int start) {
        int s = start >> 1;
        int prefix = calc(s - 1) ^ calc(s + n - 1);
        int last = n & start & 1;
        int ans = (prefix << 1) | last;
        return ans;
    }
};

Python 代码:

class Solution:
    def calc(self, x):
        if x % 4 == 0:
            return x
        elif x % 4 == 1:
            return 1
        elif x % 4 == 2:
            return x + 1
        else:
            return 0
    def xorOperation(self, n: int, start: int) -> int:
        s = start >> 1
        prefix = self.calc(s - 1) ^ self.calc(s + n - 1)
        last = n & start & 1
        ans = (prefix << 1) | last
        return ans

TypeScript 代码:

function calc(x: number): number {
    if (x % 4 === 0return x;
    else if (x % 4 === 1return 1;
    else if (x % 4 === 2return x + 1;
    else return 0;
}
function xorOperation(n: number, start: number): number {
    let s = start >> 1;
    let prefix = calc(s - 1) ^ calc(s + n - 1);
    let last = n & start & 1;
    let ans = (prefix << 1) | last;
    return ans;
};
  • 时间复杂度:
  • 空间复杂度:

最后

巨划算的 LeetCode 会员优惠通道目前仍可用 ~

使用福利优惠通道 leetcode.cn/premium/?promoChannel=acoier,年度会员 有效期额外增加两个月,季度会员 有效期额外增加两周,更有超大额专属 🧧 和实物 🎁 福利每月发放。

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

欢迎关注,明天见。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值