力扣 396:旋转函数

力扣 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

错误思路分析:本题中可以把F()看成一个函数,所有数组元素成循环状,分别与数组下标相乘,那么就要考虑这种循环开头是什么,结尾在哪。很明显在数组元素只有四个的时候,F函数从0到3共四个,那么就可以想到F函数的个数就是数组的元素个数。那么循环开始就是数组的头元素与数组下标开头0相乘到数组头元素与末尾下标(数组长度减一)相乘,就有以下代码:

不要问我为什么在这里放一个错误思路分析,我只是想让我苦思冥想俩小时有个结果(┬┬﹏┬┬)(╯°□°)╯︵ ┻━┻

class Solution{
    public int cir(int[] num) {
		int ans = 0;
		int sum=0;
		int len = num.length;
		for(int i=0;i<len;i++) {
			sum+=num[i];
			ans+=num[i]*i;
		}
		int var = ans;
		for(int i=2;i<=len;i++) {
			ans=0;
			for(int j=0;j<len;j++) {
				ans+=num[i-1]*j;
				i++;
				if(i>len) {
					i=i%len;
				}
			}
			var = Math.max(ans,var);
		}
		return var;
	}
}

为什么他是错的,因为双重循环会导致时间复杂度过大。测试用例数组数量过多,时间复杂度爆炸。

接下来是正确思路,确实大佬们比我的算法要简便得多☆*: .。. o(≧▽≦)o .。.:*☆

正确思路:在示例中,我们可以看到F(1)与F(0)和F(2)的差别:

F(0)=0 * 4 + 1 * 3 + 2 * 2 + 3 * 6 + ----- + -----

F(1)=-----  + 1 * 4 + 2 * 3 + 3 * 2 + 0 * 6 +-----

F(2)=-----  +  -----  + 2 * 4 + 3 * 3 + 0 * 2 + 1 * 6

凡是溢出(该乘的下标变为4时)的

对于后面的0和1,我们可以将其表示为:

sum = 1 * 4 + 1 * 3 + 1 * 2 + 1 * 6 

F(0)=0 * 4 + 1 * 3 + 2 * 2 + 3 * 6 

F(1)=F(0)+ sum -4*6

F(1)=(0+1)*4+(1+1)*3+(2+1)*2+(3+1-4)*6

F(2)=F(1)+ sum-4*2

F(2)=(1+1)*4+(2+1)*3+(3+1-4)*2+(0+1)*6

 也就是F(n)是F(n-1)加上数组总和减去F(n-1)里面应该乘以数组最后一个元素下标的元素的4倍,则代码是: 

class Solution {
    public int maxRotateFunction(int[] num) {
        int sum=0;
		int ans=0;
		for(int i=0;i<num.length;i++) {
			sum+=num[i];
			ans+=num[i]*i;
		}
		int len=num.length;
		int var=ans;
		for(int i=1;i<num.length;i++) {
			ans=ans+sum-len*num[len-i];
			var=Math.max(ans,var);
		}
        return var;
    }
}

 

 这种正确解法也是我在c上学习到的,为了加深印象写的这个博客,就像上图所示,把我的心得写出来教给别人提高我的理解体会,是我的学习金字塔系列,如有错误,敬请指正o(* ̄▽ ̄*)ブ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值