题目意思理解:
将一个数组分成两个数组,要求每个数组的平均值一致—和原数组平均值相等。且数组大小不一定要想等。
刚开始的想法:
因为这个题目它也是0-1问题,所以刚开始是想用动态规划来求解,但是当时确实dp数组和决策方程想不出来用什么好,因为dp数组具有子问题不必多次求解的意思在里面,但是我想不出这里的子问题与原问题之间的联系,而且dp数组里面存放的内容,我觉得好像没有太大用途,所以当时就没有继续该思路想法。
第二个思路是因为0-1还有一个想法就是二进制,所以当时想着取一个数作为固定数组是否取这个数的约定,化作二进制时为1则取,不为1则不取。—此方法名叫二进制枚举。
但是纯二进制枚举会导致数组很大,迭代次数过多,超时,因为最大位数为30位,2的30次方的迭代次数可想而知会超时。
然后最后,就是折半搜索了,就是把原来的数组分为两个数组,分为两个数组去二进制枚举。这样时间复杂度就减少了一个平方次幂。2*2的15次方时间复杂度。
代码
/**
* @param {number[]} nums
* @return {boolean}
*/
var splitArraySameAverage = function(nums) {
if(nums.length===1) return false
let len = nums.length
let b = 1
let sum = nums.reduce((x,y) => x+y,0) //利用reduce函数计算和
nums = nums.map(item =>{ //map函数让原数组和为0
return item*len - sum
})
console.log(nums)
let tot = []
/* console.log(sum/len) */
while(b<2**parseInt(len/2)){
let as = 0
let index=0
let res = []
while(2**index<=b){
let n =1 << (index++)
/* console.log(n)
console.log(n & b) */
if((n & b) === n){
as+=nums[index-1]
res.push(index-1)
}
}
/* console.log(res,as/res.length) */
tot.push(as)
if(as === 0)
return true
b+=1
console.log(b)
}
b = 2**parseInt(len/2)
let s = 0
for(let i = parseInt(len/2);i<len;i++){
s+=nums[i]
}
while(b<2**len){
let as = 0
let index=0
let res = []
while(2**index<=b){
let n =1 << (index++)
/* console.log(n)
console.log(n & b) */
if((n & b) === n){
as+=nums[index-1]
res.push(index-1)
}
}
/* console.log(res,as/res.length) */
console.log(2**len-1)
if(as === 0 || ((as!==s) && tot.includes(-as)))
return true
b+=2**parseInt(len/2)
console.log(b)
}
return false
};
let nums = [3,1]
console.log(splitArraySameAverage(nums))