805. Split Array With Same Average

In a given integer array A, we must move every element of A to either list B or list C. (B and C initially start empty.)

Return true if and only if after such a move, it is possible that the average value of B is equal to the average value of C, and B and C are both non-empty.

Example :
Input: 
[1,2,3,4,5,6,7,8]
Output: true
Explanation: We can split the array into [1,4,5,8] and [2,3,6,7], and both of them have the average of 4.5.

Note:

  • The length of A will be in the range [1, 30].

  • A[i] will be in the range of [0, 10000].

题目大意:给定一个数组, 将A中的元素挪动到B 和C 数组中,问,B和C 能否构成 average 相等的两个数组。

/*
参考: https://leetcode.com/problems/split-array-with-same-average/discuss/120660/Java-accepted-recursive-solution-with-explanation

思路: 
1) 如果B 和C 的均值 相等,那么必定 == average(A) 
2) sumB / lenOfB = sumA / lenOfA  也就是 sumB = sumA * lenOfB / lenOfA
3) 因为sumB 是个integer, 因此(sumA * lenOfB) % A.length == 0
4) 假设B 为 B,C中数量较少的数组, 则 B的长度为[1, A.length / 2]。  遍历 lengOfB 的长度, 在A中,不断递归找到lenOfB, 来看能否找到 sumB == (sumA * lenOfB) / A.length。
*/
class Solution {    
    public boolean check(int[] A, int leftSum, int leftNum, int startIndex) {  
        //递归结束条件,如果lenthOfB ==0 ,返回 sumB是否为0.
        if (leftNum == 0) return leftSum == 0;
        //如果第一个元素 已经> average, 直接return false, 因为A是排序好的。
        if ((A[startIndex]) > leftSum / leftNum) return false;
        
        //从startIndex开始 找出 leftNum 个数字,使其和为 leftSum。 因为要找出leftNum 个,因此遍历的最后一个元素为A.length-leftNum. 否则找不出足够的元素。
        for (int i = startIndex; i < A.length - leftNum + 1; i ++) {
            //如果当前的元素== 之前的元素,则直接跳过。因为 A[i-1] 在上一层的递归中已经处理过。 例子: 30[A],30[B],30[C],30[D],30[E],30[F],60
            //当startIndex == 0,leftSum = 120 时, i =0 递归进入--> startIndex2==1, leftSum = 90,遍历 (i=startIndex2<A.length - leftNum+1; i++)时,递归进入 startIndex3=2, leftSum=30。假设层层遍历完成后,退出到最上层,startIndex==0层时, i取1, 继续遍历 leftSum=90,此种情况已经遍历完成,故跳过。 
	        if (i > startIndex && A[i] == A[i - 1]) continue;
            if (check(A, leftSum - A[i], leftNum - 1, i + 1)) return true;
        }
        return false;       
    }
    
    public boolean splitArraySameAverage(int[] A) {
        if (A.length == 1) return false;
        int sumA = 0;
        sumA = Arrays.stream(A).sum();
        Arrays.sort(A);
        
        //遍历lenOfB的长度,然后从A中,递归找出lenOfB个元素是的 sumB = (sumA * lenOfB) / A.length。
        for (int lenOfB = 1; lenOfB <= A.length / 2; lenOfB ++) {
            //如果存在sumB 为integer
            if ((sumA * lenOfB) % A.length == 0) {
                // 递归查找A中,是否存在lenOfB个元素,使得其和为 (sumA * lenOfB) / A.length
                if (check(A, (sumA * lenOfB) / A.length, lenOfB, 0)) return true;
            }
        }
        return false;
        
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值