关于后端:面试高频题难度-25简单的复工面试题

2次阅读

共计 1886 个字符,预计需要花费 5 分钟才能阅读完成。

题目形容

这是 LeetCode 上的 396. 旋转函数 ,难度为 中等

Tag :「前缀和」、「滑动窗口」

给定一个长度为 $n$ 的整数数组 $nums$。

假如 $arr_k$ 是数组 $nums$ 顺时针旋转 $k$ 个地位后的数组,咱们定义 $nums$ 的 旋转函数  F 为:

  • F(k) = 0 * arrk[0] + 1 * arrk[1] + ... + (n - 1) * arrk[n - 1]

返回 F(0), F(1), ..., F(n-1) 中的最大值。

生成的测试用例让答案合乎 $32$ 位 整数。

示例 1:

输出: nums = [4,3,2,6]

输入: 26

解释:
F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 0 + 3 + 4 + 18 = 25
F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 0 + 4 + 6 + 6 = 16
F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 0 + 6 + 8 + 9 = 23
F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26
所以 F(0), F(1), F(2), F(3) 中的最大值是 F(3) = 26。

示例 2:

输出: nums = [100]

输入: 0

提醒:

  • $n = nums.length$
  • $1 <= n <= 10^5$
  • $-100 <= nums[i] <= 100$

前缀和 + 滑动窗口

为了不便,咱们将 $nums$ 的长度记为 $n$。

题目要对「旋转数组」做逻辑,容易想到将 $nums$ 进行复制拼接,失去长度为 $2 \times n$ 的新数组,在新数组上任意一个长度为 $n$ 的滑动窗口都对应了一个旋转数组。

而后思考在窗口的滑动过程中,计算结果会如何变动,假如以后咱们解决到下标为 $[i, i + n – 1]$ 的滑动窗口,依据题意,以后后果为:

$$
cur = nums[i] \times 0 + nums[i + 1] \times 1 + … + nums[i + n – 1] \times (n – 1)
$$

当窗口往后挪动一位,也就是窗口的右端点来到 $i + n$ 的地位,左端点来到 $i + 1$ 的地位。

咱们须要减少「新右端点」的值,即减少 $nums[i + n] \times (n – 1)$,同时减去「旧左端点」的值,即缩小 $nums[i] \times 0$(固定为 $0$),而后更新新旧窗口的公共局部 $[i + 1, i + n – 1]$。

不难发现,随着窗口的逐渐右移,每一位公共局部的权值系数都会进行减一。

$$
nums[i + 1] \times 1 + nums[i + 2] \times 2 + … + nums[i + n – 1] \times (n – 1)
$$

变为

$$
nums[i + 1] \times 0 + nums[i + 2] \times 1 + … + nums[i + n – 1] \times (n – 2)
$$

因而,公共局部的差值为 $\sum_{idx = i + 1}^{i + n – 1}nums[idx]$,这疏导咱们能够应用前缀和进行优化。

至此,咱们从旧窗口到新窗口的过渡,都是 $O(1)$,整体复杂度为 $O(n)$。

实现上,咱们并不需要真正对 $nums$ 进行复制拼接,而只须要在计算前缀和数组 $sum$ 进行简略的下标解决即可。

代码:

class Solution {public int maxRotateFunction(int[] nums) {
        int n = nums.length;
        int[] sum = new int[n * 2 + 10];
        for (int i = 1; i <= 2 * n; i++) sum[i] = sum[i - 1] + nums[(i - 1) % n];
        int ans = 0;
        for (int i = 1; i <= n; i++) ans += nums[i - 1] * (i - 1);
        for (int i = n + 1, cur = ans; i < 2 * n; i++) {cur += nums[(i - 1) % n] * (n - 1);
            cur -= sum[i - 1] - sum[i - n];
            if (cur > ans) ans = cur;
        }
        return ans;
    }
}
  • 工夫复杂度:$O(n)$
  • 空间复杂度:$O(n)$

最初

这是咱们「刷穿 LeetCode」系列文章的第 No.396 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,局部是有锁题,咱们将先把所有不带锁的题目刷完。

在这个系列文章外面,除了解说解题思路以外,还会尽可能给出最为简洁的代码。如果波及通解还会相应的代码模板。

为了不便各位同学可能电脑上进行调试和提交代码,我建设了相干的仓库:https://github.com/SharingSou…。

在仓库地址里,你能够看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其余优选题解。

更多更全更热门的「口试 / 面试」相干材料可拜访排版精美的 合集新基地 🎉🎉

本文由 mdnice 多平台公布

正文完
 0