【面试高频题】难度 2/5,简单的复工面试题

拓朴苔原
• 阅读 333

题目描述

这是 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多平台发布

点赞
收藏
评论区
推荐文章
cpp加油站 cpp加油站
4年前
题解5道c++面试题第一期(含解题思路、答案解析和实现代码)
本篇文章送上5道c/c面试题目,并附上答案、解题思路以及扩展知识。1.求下面函数的返回值cinclude<stdio.hintfunc(intx)intiCnt0;while(x)iCnt;xx&(x1);returniCnt;intmain()printf("cnt%d\n",func(9999
作为一个码农终于把这些笔记看懂了,牛皮轰轰
Spring面试高频问题SpringMVC面试高频问题MyBatis面试高频问题SpringBoot面试高频题SpringCloud面试高频问题Redis高级面试题Dubbo高频常问面试问题Java虚拟机(JVM)MySQL数据库高频面试问题Java高频面试专题合集解析:当然在这还有更多整理总结的Java进阶学习笔记和面试题未展示,在这也是
Stella981 Stella981
3年前
Leetcode Index
序:  用于记录刷题过程中难度较大或思路怪异的题目,对于常规难度一般的题就不写入我的博客了,关于效率仅是提交时击败的百分比,可能会随时间波动,仅供参考,算法优劣以时间复杂度和空间复杂度为基准。欢迎留言讨论。题目序号难度效率Leetcode42.TrappingRainWater(https://www.oschina.
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
LeetCode刷题实战61:旋转链表
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选!今天和大家聊的问题叫做旋转链表,我们先来看题面:https://leetcodecn.com/problems/rotatelist/Give
Stella981 Stella981
3年前
Golang之如何(优雅的)比较两个未知结构的json
这是之前遇到的一道面试题,后来也确实在工作中实际遇到了。于是记录一下,如何(优雅的)比较两个未知结构的json。假设,现在有两个简单的json文件。{"id":1,"name":"testjson01","isadmin":true}{"isadmi
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(