javascript-非负集减

这适用于任何语言,但是我会在node中实现它.

我有一组整数,并且需要从该组的总和中减去一个值.

[4, 5, 6, 7, 8] - 25

如果我们从每个数字中平均减去,我们将得到:

[-1, 0, 1, 2, 3]

但是,我不希望任何数字小于0.因此,如果我正在编写算法来执行此操作,则负数将相等地溢出到其余数字中,现在我们有了:

[0, 0, 1, 2, 3] - 1

生成结果集:

[0, 0, 1 - 0.333, 2 - 0.333, 3 - 0.333]

是否有任何快速操作或一系列操作不涉及循环直到完成才能解决此问题?

请注意,这正是我想要的结果.所有的负值甚至会溢出到其余的正值中.

我使用Lodash,所以用Lodash回答是可以接受的.

解决方法:

假设设置了数量,则可以减少很多所需的循环

>仅具有正值
>集合的总和大于要减去的值
>可以排序.

关于第3点,您在评论中说可以对此进行排序,所以这是我想到的算法.就变量名而言,它很冗长,但希望可以使它更清晰.总而言之,它并不太复杂:

const result = subtractFromSet([4, 5, 6, 7, 8], 25);
console.log(result)

function subtractFromSet(numberSet, totalToSubtract) {
  return numberSet.map((currentMember, index, wholeSet) => {
    const remainingElements = wholeSet.length - index
    const averageToSubtract = totalToSubtract / remainingElements;
    
    const toSubtract = Math.min(averageToSubtract, currentMember);
    //modify both the total remaining to subtract and the current element
    totalToSubtract -= toSubtract;
    return currentMember - toSubtract;
  })
}

用言语解释一下,这是正在发生的事情

>从集合的总和中减去一个值等于从每个成员中减去该值除以集合的大小.因此[4、5、6、7、8]-25将是4-5、5-5、6-5等.
>如果我们不想要负数,那么我们只减去当前成员.因此,在当前成员为4且平均值为25/5 = 5的情况下,我们只能减去4.
>为了分散余数,我们只需将其加回到余数中即可减去其余成员.因此,当我们到达第二个成员5时,平均值现在为(25-4)/(5-1),因为我们第一次不能减去全部5个平均值,只有4个,其余元素少一个.这产生5.25.

因此,当遍历每个成员并调整总和然后减去所需的平均值时,我们得到正确的结果.尽管请注意编程中的floating point arithmetic,因为它可能导致结果略有偏差.如果您舍入足够的重要数字来满足需要,则可以避免这种情况.

最后一件事-正如我所说,输入必须进行排序.可以像这样轻松完成:

const unsortedArray = [6, 4, 7, 8, 5];
const sortedArray = unsortedArray.sort((a, b) => a - b)

console.log(sortedArray);

我从上面的算法中忽略了它,专注于我们对已排序输入的实际操作.

该算法的总复杂度相当不错-合理的排序将使您节省O(n log(n))的时间复杂度.取决于排序的实现方式和数据集-可能通过O(n ^ 2)Bubblesort对5个元素进行排序,但是再一次,它是5个元素,因此可能不会产生影响.运行减法算法是一个简单的O(n).减法的空间复杂度为O(2n),因为.map()复制了数组.我选择它是因为它比较干净,因为您仍有输入.但是,您也可以通过最小的更改就地进行减法,这将使您的空间复杂度达到O(n).

const input = [4, 5, 6, 7, 8];
subtractFromSet(input, 25);
console.log(input);

function subtractFromSet(numberSet, totalToSubtract) {
  numberSet.forEach((currentMember, index, wholeSet) => { //using .forEach instead of .map
    const remainingElements = wholeSet.length - index
    const averageToSubtract = totalToSubtract / remainingElements;
    
    const toSubtract = Math.min(averageToSubtract, currentMember);
    //modify both the total remaining to subtract and the current element
    totalToSubtract -= toSubtract;
    wholeSet[index] = currentMember - toSubtract; //modify the array directly
  })
}
上一篇:javascript-使用lodash的递归循环


下一篇:javascript-多级对象-基于键的破坏性合并