-
题目描述:
-
题目化简:
对数组的所有子数组分别进行一定操作(求最小值*元素和)后求和。 -
思路
(1)找到最小值,将数组分为 包含该值的所有子数组和不包含该值的所有子数组。
(2)不包含该值的所有子数组,可以分为左右两个单独数组,进行递归操作。
(3)问题到此化简为,对数组所有子数组内的元素求和,再求和。
问题聚焦为:每个元素被加了多少遍,及即包含min和该元素的子数组共有多少个。
找规律发现,该值为(左侧元素个数+1)*(右侧元素个数+1),代码如下:
for(int j = 0 ; j<n ; j++){
long temp = (long)(Math.min(j,point)+1) * (n-Math.max(j,point)) ;
temp2 =temp2 + strength[j] * temp;
}
-
执行测试用例发现的问题
(1)程序中乘法或者加法超过Int范围问题
先将Int转换成long后再操作,最后对long进行取余。
(2)递归造成的内存不足问题
用循环替代递归 -
代码
class Solution {
public int totalStrength(int[] strength) {
int n = strength.length;
if(n == 1){
long temp4 = (long)strength[0] * strength[0]; // int 转换成 long 再 乘
temp4 = temp4 % ((long)(Math.pow(10.0,9.0)) + 7) ;
return (int)temp4;
}
int left = 0 ;
int right = 0;
long mid = 0;
int min = Integer.MAX_VALUE;
int point = 0;
int secfen = n/2;
int flag =Integer.MAX_VALUE;
for(int i=0 ; i<n;i++){
if(strength[i]<min) {
min = strength[i];
point = i ;
}
else if(strength[i]==min){
int dis = Math.abs(point - secfen);
if(dis<flag){
point = i ;
flag = dis;
}
}
}
if(point != 0 ) left = totalStrength(Arrays.copyOfRange(strength,0,point));
if(point != n-1) right= totalStrength(Arrays.copyOfRange(strength,point+1,n));
long temp2 =0;
for(int j = 0 ; j<n ; j++){
long temp = (long)(Math.min(j,point)+1) * (n-Math.max(j,point)) ; // int 转换成 long 再 乘
temp2 =temp2 + strength[j] * temp;
temp2 = temp2 % ((int)(Math.pow(10.0,9.0)) + 7) ;
}
mid = (long)min * temp2;
long temp3 = mid + left + right;
temp3 = temp3 % ((int)(Math.pow(10.0,9.0)) + 7) ; // 去掉了 判断
int all = (int)temp3;
return all;
}
}