题目
给定一个长度为 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 <= 10^5
-100 <= nums[i] <= 100
思考
这是今日的每日一题,难度是中等。
首先是看懂题意。对于给出是数组nums,旋转函数
的含义是对数组元素进行特定的操作,最后返回一个新的数值。旋转一次是将数组的最后一个元素放到操作的最前面。
定义数组元素之和为sum。通过观察题目,不难得出以下规律:
F(0) = 0*nums[0] + 1*nums[1] + ... + (n-1)*nums[n-1]
F(1) = 1*nums[0] + 2*nums[1] + ... + (n-1)*nums[n-2] + 0*nums[n-1] = F(0) + sum - n*nums[n-1]
// 那么,
F(k) = F(k-1) + sum - n*nums[n-k], 1≤k<n
那么我们可以一次迭代求出F(k),然后求出其中的最大值。
解答
方法一:迭代
/**
* @param {number[]} nums
* @return {number}
*/
var maxRotateFunction = function(nums) {
let len = nums.length, f = 0
if (len === 1) {
return 0
}
// 求数组元素之和
let sum = nums.reduce((prev, num) => prev + num, 0)
// 求F(0)
for (let i = 0; i < len; i++) {
f += i * nums[i]
}
// 最大值
let max = f
// 求F(1), F(2), ...
for (let i = len - 1; i > 0; i--) {
f += sum - len * nums[i]
max = Math.max(max, f)
}
return max
}
// 执行用时:84 ms, 在所有 JavaScript 提交中击败了87.84%的用户
// 内存消耗:51.4 MB, 在所有 JavaScript 提交中击败了60.81%的用户
// 通过测试用例:58 / 58
复杂度分析:
- 时间复杂度:
O(n)
,其中 n 是数组 nums 的长度。 - 空间复杂度:
O(1)
,仅使用了常数空间。