一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
前言
今天的题目为中等,属于偏向于数学的找规律题目,能够多写出来两个例子,看一下和之间的关系,应该是不难发现其中的规律,再知道了规律之后,这就是一道简单题了。
每日一题
今天的题目是 396. 旋转函数,难度为中等
-
给定一个长度为 n 的整数数组 nums 。
-
假设 arrk 是数组 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 <= 105
- -100 <= nums[i] <= 100
题解
滑动窗口找规律
经典的数学找规律题目,之前我们提到过,一个数组的旋转,可以看为两个这个数组拼接之后的滑动窗口。
这样每次移动的时候,我们要减去右端点,加上左端点,我们将两倍的数组长度记为2n,现在从n-2n开始往0移动,设第一个窗口的和为 sum
假设当前我们处理到下标为 [n-i-1, 2n-i-1] 的滑动窗口,根据题意,当前结果为:
cur = nums[n-i-1] * 0 + nums[n-i+1-1] * 1 + ... + nums[2n-i-1] * (n - 1)
然后每一次的移动,都会让左端点的值增加一个,右端点的值减少一个,既
next = nums[n-i-1+1] * 0 + nums[n-i+1-1+1] * 1 + ... + nums[2n-i-1+1] * (n - 1)*
我们将两个相减就能够发现
cur-next = nums[n-i-1]+nums[n-i-1+1]+···+nums[2n-i-1]-n*nums[n-i-1]
可以看出 nums[n-i-1]+nums[n-i-1+1]+···+nums[2n-i-1] 就是 sum-nums[n-i-1]
所以最后我们能够得到两个前后方程式的关系
next=cur-sum+n*num[i-1]
然后根据得到的方程式进行迭代就可以得出答案:
/**
* @param {number[]} nums
* @return {number}
*/
var maxRotateFunction = function(nums) {
let n = nums.length
let cur = [0]
let sum = 0
for(let i=0;i<n;i++){
sum+=nums[i]
cur[0]+=(i*nums[i])
}
let res = cur[0]
for(let i=1;i<n;i++){
cur[i] = cur[i-1]-sum+n*nums[i-1]
res=Math.max(cur[i],res)
}
return res
};