GithubHelp home page GithubHelp logo

第 13 题:有一堆整数,请把他们分成三份,确保每一份和尽量相等(11,42,23,4,5,6 4 5 6 11 23 42 56 78 90) about fe-interview HOT 27 OPEN

lgwebdream avatar lgwebdream commented on May 1, 2024 22
第 13 题:有一堆整数,请把他们分成三份,确保每一份和尽量相等(11,42,23,4,5,6 4 5 6 11 23 42 56 78 90)

from fe-interview.

Comments (27)

QiuYiLiang avatar QiuYiLiang commented on May 1, 2024 12
function f1 (arr,count){
    //数组从大到小排序
    arr.sort((a,b) => b - a);
    //计算平均值
    let avg = arr.reduce((a,b) => a + b) / count;
    //从大到小求和,取最接近平均值的一组,放入二维数组
    let resArr = [];
    let current = 0;
    for (let i = 0; i < count-1; i++) {
        if(current + arr[arr.length-1]/2 < avg && i){
            arr.pop();
            resArr[i-1].push(arr[arr.length-1]);
        }
        current = 0;
        resArr[i] = [];
        arr.forEach((item,index) => {
            current += item;
            arr.splice(index,1);
            resArr[i].push(item);
            if(current > avg){
                current -= item;
                arr.splice(index,0,item);
                resArr[i].pop();
            }
        })
    }
    resArr[count-1] = arr;
    return resArr
}
//测试,第一个参数为数组,第二个为份数
f1([11,42,23,4,5,6,4,5,6,11,23,42,56,78,90],3)

from fe-interview.

licong-site avatar licong-site commented on May 1, 2024 5

@Genzhen
// 在某些情况下获取的不是最优解
// 输入 [1,2,3,4,5,6,7,8]
// 结果是: [[8, 3, 2], [6, 5, 1], [7, 4]] 三个数组项的和分别为 13,12,11
// 最优解应该为 [[8, 4], [6, 5, 1], [7, 3, 2]] 三个数组项的和分别为 12,12,12

from fe-interview.

qzruncode avatar qzruncode commented on May 1, 2024 5
**:排序+双端遍历 即可实现
function findPart(arr) {
  arr = arr.sort((a, b) => a - b);
  const sum = arr.reduce((pre, cur) => pre + cur, 0);
  const part = Math.floor(sum / 3);
  function getPart() {
    const tmp = [];
    let i = 0, j = arr.length - 1;
    while(i <= j) {
      let flag = false;
      let tmpSum = tmp.reduce((pre, cur) => pre + cur, 0);
      if((tmpSum + arr[i]) <= part) {
        flag = true;
        tmp.push(arr[i]);
        i++;
      }
      if((tmpSum + arr[j]) <= part) {
        flag = true;
        tmp.push(arr[j]);
        j++;
      }
      if(!flag){
        break;
      }
    }
    arr = arr.slice(i, j - 1);
    return tmp;
  }
  return [getPart(), getPart(), getPart()];
}
findPart([11,42,23,4,5,6,4,5,6,11,23,42,56,78,90]);

结果
[4, 90, 4, 5, 5, 6, 6, 11]
[11, 78, 23, 23]
[42, 56]

from fe-interview.

dolphin0618 avatar dolphin0618 commented on May 1, 2024 4
var a = [11, 42, 23, 4, 5, 6, 4, 5, 6, 11, 23, 42, 56, 78, 90]
var res = [{sum: 0, arr: []}, {sum: 0, arr: []}, {sum: 0, arr: []}]
// 从大到小排序,最后放细沙
a.sort((a,b) => b-a).map(el => {
   var min = res.sort((a,b) => a.sum - b.sum)[0]
    min.sum += el
    min.arr.push(el)
})

res.map(el => el.arr)

from fe-interview.

nhyu avatar nhyu commented on May 1, 2024 3
// 思路:把大的数插入数组,再用小的数找齐三组数和的差距,就可以尽量均匀的分成三组了。
// 代码逻辑:数组从大到小排序,把数依次往和最小的数组中插入。
function sliceArray(arr) {
    const newErr = [...arr].sort((a, b) => b - a); // 一定要倒序排列,大的排在前面。
    const arr1 = [], arr2 = [], arr3 = []; // 用于储存结果的三个数组
    let arr1Sum = 0, arr2Sum = 0, arr3Sum = 0; // 三个数组对应数的和

    for (const item of newErr) {
        const min = Math.min(arr1Sum, arr2Sum, arr3Sum);
        switch (min) {
            case arr1Sum:
                arr1.push(item);
                arr1Sum += item;
                break;
            case arr2Sum:
                arr2.push(item);
                arr2Sum += item;
                break;
            case arr3Sum:
                arr3.push(item);
                arr3Sum += item;
                break;

            default:
                break;
        }
    }
    return [arr1, arr2, arr3];
}

from fe-interview.

Genzhen avatar Genzhen commented on May 1, 2024 2
function foo(arr) {
        let AMOUNT = arr.length
        if (!AMOUNT) return false;
        if (AMOUNT === 3) return arr;
        arr.sort((a, b) => a - b);
        let total = 0;
        let maxNumberTotal = 0;
        for (let i = 0; i < AMOUNT; i++) {
            total += arr[i];
        }
        maxNumberTotal = total / 3;
        let tempTotal = arr[AMOUNT - 1];

        let firstArr = [arr[AMOUNT - 1]];
        let delIndex = [AMOUNT - 1];
        let firstIndex = -1;

        // 获取第一份数组
        for (let i = AMOUNT - 2; i > 0; i--) {
            const el = arr[i];
            tempTotal += el; // 每次拿最大的;
            firstArr.push(el);
            delIndex.push(i);
            if (tempTotal === maxNumberTotal) { // 刚好等于最大值跳出循环
                break;
            } else if (tempTotal > maxNumberTotal) { // 发现超过最大值, 减回去
                tempTotal -= el;
                delIndex.pop();
                firstArr.pop();
            } else if (tempTotal < maxNumberTotal) { // 发现超过最小值, 处理边界问题
                let nextTotal = tempTotal + arr[i + 1]
                if (maxNumberTotal - tempTotal < Math.abs(maxNumberTotal - nextTotal)) { // 当前总值比上一个总值大; 这里是临界值, 说明上一个总值肯定是一个比最大值大, 所以这里需要和绝对值比较
                    if (maxNumberTotal - tempTotal > arr[0]) { // 如果下一个平局值和总值相减, 比数组第一个数还大, 说明还可以继续走下去;
                        continue;
                    } else {
                        break;
                    }
                }
            }
        }
        for (let i = 0; i < delIndex.length; i++) {
            arr.splice(delIndex[i], 1)            
        }

        AMOUNT = arr.length; // 注意每次的arr都是不一样的
        let secondArr = [arr[AMOUNT - 1]];
        delIndex = [AMOUNT - 1];
        let secondIndex = -1;
        tempTotal = arr[AMOUNT - 1];
        // 获取第二份数组
        for (let i = AMOUNT - 2; i > 0; i--) {
            const el = arr[i];
            tempTotal += el; // 每次拿最大的;
            secondArr.push(el);
            delIndex.push(i);
            if (tempTotal === maxNumberTotal) { // 刚好等于最大值跳出循环
                break;
            } else if (tempTotal > maxNumberTotal) { // 发现超过最大值, 减回去
                tempTotal -= el;
                delIndex.pop();
                secondArr.pop();
            } else if (tempTotal < maxNumberTotal) { // 发现超过最小值, 处理边界问题
                let nextTotal = tempTotal + arr[i + 1]
                if (maxNumberTotal - tempTotal < Math.abs(maxNumberTotal - nextTotal)) { // 当前总值恒小于下一个总值; 这里是临界值
                    if (maxNumberTotal - tempTotal > arr[0]) {
                        continue;
                    } else {
                        break;
                    }
                }
            }
        }
        for (let i = 0; i < delIndex.length; i++) {
            arr.splice(delIndex[i], 1)            
        }
        // 公平处理, 当出现极差情况就需要做公平处理了, 这里暂时不考虑极差情况
        return [firstArr, secondArr, arr]
    }

from fe-interview.

Aeolos1994 avatar Aeolos1994 commented on May 1, 2024 2

没这么麻烦吧 其实直接就是瀑布流布局的**啊
function makeAlmostEqual (arr, part) {
let orderedArr = arr.sort((a,b) => b - a)
let res = Array(part).fill(void(0)).map(() => [])
orderedArr.forEach(value => {
let minArrIndex = getMinArrIndex(res)
res[minArrIndex].push(value)
})
return res
}

function getSum (arr) {
return arr.reduce((sum, v) => sum + v, 0)
}

function getMinArrIndex (arrs) {
let minArrIndex = 0
arrs.forEach((arr, index) => {
if (getSum(arrs[minArrIndex]) > getSum(arrs[index])) {
minArrIndex = index
}
})
// console.log(arrs)
return minArrIndex
}

makeAlmostEqual([1, 65, 4, 32, 95, 33, 9, 3], 3)

只要注意数组要倒序排列就好了

from fe-interview.

AielloChan avatar AielloChan commented on May 1, 2024 2

leetcode 有类似的题吗?

from fe-interview.

Genzhen avatar Genzhen commented on May 1, 2024 1

leetcode 有类似的题吗?

@AielloChan 在leetcode 可以练习自己的解题思路,培养解题思维,练的多了,看到这样的题,就会知道怎么去解了,在leetcode 也不要盲目的从头开始刷,最好是分类练习

from fe-interview.

qzruncode avatar qzruncode commented on May 1, 2024 1

@zxmajunhong 算法题不是用来实际用的,是来练你的逻辑思维和语法熟练度的,理论和实际是两码事,理论好了实操才会更好,没有理论支持,实操能好到哪儿去?最多也是搬砖工

from fe-interview.

pws019 avatar pws019 commented on May 1, 2024

// 若总和不能被 3 整除,说明不能分成相等的 3 个部分,然后return了,题目不是说尽量相等嘛???

from fe-interview.

Genzhen avatar Genzhen commented on May 1, 2024

// 若总和不能被 3 整除,说明不能分成相等的 3 个部分,然后return了,题目不是说尽量相等嘛???

答题已更新哈

from fe-interview.

BruceYuj avatar BruceYuj commented on May 1, 2024

题目来自于背包问题变种,思路比较简单,动态规划解决。

from fe-interview.

duoduoing avatar duoduoing commented on May 1, 2024
const numSort = (arr) => {
  return arr.sort((a, b) => b - a)
};
const numArr = numSort([11, 42, 23, 4, 5, 6, 4, 5, 6, 11, 23, 42, 56, 78, 90]);
const sumTotal = eval(numArr.join('+'));
let a = 0, b = 0, c = 0;
const sumFN = (x) => {
  let newX = x;
  numArr.map((num, index) => {
    if ((newX + num) <= Math.ceil(sumTotal / 3)) {
      newX = newX + num;
      numArr.splice(index, 1);
    } else {
      return false;
    }
  })
  return newX
};
a = sumFN(a);
b = sumFN(b);
c = eval(numArr.join('+'));
console.log(a, b, c);
136 136 134

from fe-interview.

Genzhen avatar Genzhen commented on May 1, 2024

// 若总和不能被 3 整除,说明不能分成相等的 3 个部分,然后return了,题目不是说尽量相等嘛???

感谢指出问题,答案已更新哈

from fe-interview.

Genzhen avatar Genzhen commented on May 1, 2024

@Genzhen
// 在某些情况下获取的不是最优解
// 输入 [1,2,3,4,5,6,7,8]
// 结果是: [[8, 3, 2], [6, 5, 1], [7, 4]] 三个数组项的和分别为 13,12,11
// 最优解应该为 [[8, 4], [6, 5, 1], [7, 3, 2]] 三个数组项的和分别为 12,12,12

感谢指出问题,答案已更新哈

from fe-interview.

pioneer22 avatar pioneer22 commented on May 1, 2024
function sliceArray (arr, count) {
  // 平均值向上取整
  let average = Math.ceil(arr.reduce((acc, v) => acc + v, 0) / count)
  // 由大到小排列
  arr.sort((n1, n2) => n2 - n1)
  const getArr = () => {
    let sum = 0, newArr = [] // 存相应数据
    arr.map((v, i) => {
      if (sum + v <= average) {
        sum += v
        newArr.push(v)
        arr.splice(i, 1)
      }
    })
    return newArr;
  }

  let backArr = new Array(count).fill(0)
  backArr.forEach((x, i) => {
    backArr[i] = i === backArr.length - 1 ? arr : getArr()
  })
  return backArr
}

from fe-interview.

FlyingRabbit7 avatar FlyingRabbit7 commented on May 1, 2024

输入 [1,1,12,12]
结果是: [[1], [1], [12,12]] 三个数组项的和分别为 1,1,24
最优解应该为 [[1, 1], [12], [12]] 三个数组项的和分别为 2,12,12

from fe-interview.

Genzhen avatar Genzhen commented on May 1, 2024

输入 [1,1,12,12]
结果是: [[1], [1], [12,12]] 三个数组项的和分别为 1,1,24
最优解应该为 [[1, 1], [12], [12]] 三个数组项的和分别为 2,12,12

@FlyingRabbit7 感谢指出问题Thanks♪(・ω・)ノ 答案已更新哈

from fe-interview.

jimwjl666 avatar jimwjl666 commented on May 1, 2024
let arr = [11,42,23,4,5,6,4,5,6,11,23,42,56,78,90]
    arr.sort((a,b)=>a-b)
    let arr0 = []
    let arr1 = []
    let arr2 = []
    let getsum = function(arr){
        return arr.reduce((a,b)=>{
        return a+b
    },0)
    }
    let sum = getsum(arr)
    let avg = sum/3
    console.log(avg)
    // 先分大数,大数影响分布均衡
    while(arr.length>0){
      // console.log(arr.length)
      let sum0 = getsum(arr0)
      let sum1 = getsum(arr1)
      let sum2 = getsum(arr2)

      if(Math.min(sum0,sum1,sum2)===sum0 && sum0<=avg){
        let popnum = arr.pop()
        arr0.push(popnum||0)
      }
      if(Math.min(sum0,sum1,sum2)===sum1 && sum1<=avg){
        let popnum = arr.pop()
        arr1.push(popnum||0)
      }
      if(Math.min(sum0,sum1,sum2)===sum2 && sum2<=avg){
        let popnum = arr.pop()
        arr2.push(popnum||0)
      }
    }
  console.log(arr0,arr1,arr2,getsum(arr0),getsum(arr1),getsum(arr2)) // 
 [90, 23, 11, 6, 5]  [78, 42, 11, 4]  [56, 42, 23, 6, 5, 4] 135 135 136

from fe-interview.

TurnerXi avatar TurnerXi commented on May 1, 2024

function f1(arr, count) {
arr.sort((a, b) => a - b);
let max = 0;
const sums = Array(count).fill(0);
const arrs = Array(count).fill(0).map(() => []);

while (arr.length > 0) {
for (let i = 0; i < count && arr.length > 0; i++) {
if (sums[i] <= max) {
const item = arr.pop();
sums[i] += item;
arrs[i].push(item);
} else {
max = sums[i];
}
}
}
console.log(arrs, sums);
return arrs;
}

//测试,第一个参数为数组,第二个为份数
f1([1, 2, 3, 4, 5, 6, 7, 8], 3)

from fe-interview.

zxmajunhong avatar zxmajunhong commented on May 1, 2024

能说说这个的实际应用场景吗

from fe-interview.

zouqianghtml avatar zouqianghtml commented on May 1, 2024

没这么麻烦吧 其实直接就是瀑布流布局的**啊
function makeAlmostEqual (arr, part) {
let orderedArr = arr.sort((a,b) => b - a)
let res = Array(part).fill(void(0)).map(() => [])
orderedArr.forEach(value => {
let minArrIndex = getMinArrIndex(res)
res[minArrIndex].push(value)
})
return res
}

function getSum (arr) {
return arr.reduce((sum, v) => sum + v, 0)
}

function getMinArrIndex (arrs) {
let minArrIndex = 0
arrs.forEach((arr, index) => {
if (getSum(arrs[minArrIndex]) > getSum(arrs[index])) {
minArrIndex = index
}
})
// console.log(arrs)
return minArrIndex
}

makeAlmostEqual([1, 65, 4, 32, 95, 33, 9, 3], 3)

只要注意数组要倒序排列就好了

@Aeolos1994
// 在某些情况下获取的不是最优解
// 输入 [1,2,3,4,5,6,7,8]
// 结果是: [[8, 3, 2], [7, 4, 1], [6, 5]] 三个数组项的和分别为 13,12,11
// 最优解应该为 [[8, 4], [6, 5, 1], [7, 3, 2]] 三个数组项的和分别为 12,12,12

from fe-interview.

SnailOwO avatar SnailOwO commented on May 1, 2024
function f1 (arr,count){
    //数组从大到小排序
    arr.sort((a,b) => b - a);
    //计算平均值
    let avg = arr.reduce((a,b) => a + b) / count;
    //从大到小求和,取最接近平均值的一组,放入二维数组
    let resArr = [];
    let current = 0;
    for (let i = 0; i < count-1; i++) {
        if(current + arr[arr.length-1]/2 < avg && i){
            arr.pop();
            resArr[i-1].push(arr[arr.length-1]);
        }
        current = 0;
        resArr[i] = [];
        arr.forEach((item,index) => {
            current += item;
            arr.splice(index,1);
            resArr[i].push(item);
            if(current > avg){
                current -= item;
                arr.splice(index,0,item);
                resArr[i].pop();
            }
        })
    }
    resArr[count-1] = arr;
    return resArr
}
//测试,第一个参数为数组,第二个为份数
f1([11,42,23,4,5,6,4,5,6,11,23,42,56,78,90],3)

你这有个bug,就是current > avg的时候,arr再splice回去后,arr forEach的index会受影响。
let arr = [11, 42, 23, 4, 5, 6, 4, 5, 6]
我试这个的时候发现的。不过好棒,我也想到这么做了,但是没写出来!学习了~

from fe-interview.

SnailOwO avatar SnailOwO commented on May 1, 2024
// 借助上面大佬们的**写出来的改版
 let arr = [11, 42, 23, 4, 5, 6, 4, 5, 6, 11, 23, 42, 56, 78, 90]

    function f1(arr, count) {
        // 从大到小排序
        arr.sort((a, b) => b - a)
            // 求和 & 平均数
        const avg = Math.ceil(arr.reduce((acc, cur) => acc + cur) / count)
            // for循环相加
        const resAry = []
        for (let i = 0; i < count - 1; i++) {
            let total = 0
            resAry[i] = []
            arr.forEach((item, index) => {
                if (avg >= total + item) {
                    total += item
                    resAry[i].push(item)
                    arr.splice(index, 1)
                }
            })
        }
        resAry[count - 1] = arr
        return resAry
    }
`

from fe-interview.

AAA611 avatar AAA611 commented on May 1, 2024

@SnailOwO ,输入[1,2,3,4]不是最优解

from fe-interview.

facethesunsea avatar facethesunsea commented on May 1, 2024
var a = [11, 42, 23, 4, 5, 6, 4, 5, 6, 11, 23, 42, 56, 78, 90]
var res = [{sum: 0, arr: []}, {sum: 0, arr: []}, {sum: 0, arr: []}]
// 从大到小排序,最后放细沙
a.sort((a,b) => b-a).map(el => {
   var min = res.sort((a,b) => a.sum - b.sum)[0]
    min.sum += el
    min.arr.push(el)
})

res.map(el => el.arr)

思路跟你一样,但你的代码超简洁

from fe-interview.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.