算法
多重背包问题 - 每个物品最多个 n 个
const knapsack = (weights:number[], values:number[], numbers:number[], total:number) => {
var n = weights.length;
var f = [[]];
f[-1] = new Array(total+1).fill(0);
for(var i=0; i<n; i++){
f[i] = new Array(total).fill(0);
for(var j=0; j<=total; j++){
if(j < weights[i]){
f[i][j] = f[i-1][j];
}else{
for(var k = 1; k*weights[i] <= j && k<= numbers[i]; k++){
f[i][j] = Math.max(f[i-1][j], f[i-1][j-k * weights[i]] + values[i] * k);
}
}
}
}
var totalWeight = 0,
j = total;
for(var i=n;i--;){
if(f[i][j] > f[i-1][j]){
var k = 0;
while(f[i][j] - f[i-1][j - weights[i]] === values[i] && k < numbers[i]){
k++;
j -= weights[i];
}
totalWeight += weights[i] * k;
console.log(`选择物品:${k} 个 ${i};重量为:${weights[i] * k};价值为:${values[i] * k}`);
}
}
console.log(`背包最大承重:${total};实际重量:${totalWeight};最大价值:${f[n-1][total]}`)
}
knapsack([2,3,1],[2,3,4],[1,4,1],6)
闭包
在 js 中闭包可以理解为环境变量的引用。由于 js 的函数执行是用栈进行存储的,所以出栈时,相关函数的环境变量,都会被回收。如果有一些异步操作想要使用该环境变量中的部分变量。就需要使用闭包了。
变量引用不全是闭包
const foo = () => {
var a = 1;
const getA = () => {
console.log(a);
}
}
上述的情况也使用到了外层的环境变量,但是我们并不认为这种情况是闭包。因为在 foo 出栈的时候,a 和 getA 都是内部的环境变量,这个时候外部没有对这两个变量进行持有,都会被回收掉。
真正意义上的闭包
const foo = () => {
var a = 1;
const getA = () => {
console.log(a);
}
return getA;
}
var fooA = foo();
现在 foo 方法将一个函数返回给了 fooA,所以外部变量对 getA 有了引用,此时 getA 内部的函数调用持有 foo 的环境变量 a 的引用。所以 foo 执行完毕之后,依旧不会释放掉内部的环境变量。
就算我们执行完 fooA() 也不会释放掉 foo 的环境变量。只有当 fooA = null 的时候,getA 发现自己没有被引用了,下一次 gc 的时候才会回收。
闭包优化
上面的流程可以看出来,闭包有好处,可以引用到环境变量,这里用到的词是引用,不是复制,两者会有差别,复制只是多了一个变量,引用将整个环境变量持有。
基于这样就在现有的闭包机制下,优化了环境变量的持有。
function outer () {
var x; // 真正的局部变量
var y; // context variable, 被inner1使用
var z; // context variable, 被inner2使用
function inner1 () {
use(y);
}
function inner2 () {
use(z);
}
function inner3 () {
/* 虽然函数体为空,但是作为闭包,依旧引用outer的Context */
}
return [inner1, inner2, inner3];
}
上述的情况的话,x 是不会被放到闭包的环境变量中的,也就是说真正被引用到的环境变量才会放入一个闭包的机制中。
上述的情况当 inner1 执行完毕之后,也不会立刻释放 y,inner2 也不会立刻释放 z,(y,z,content) 会被一起当做一个闭包变量保存着。
即使 inner3 并没有引用任何变量,但其实是引用了 content 这样的环境变量。
所以只有当 inner1, inner2, inner3 都不再被引用时。才会释放掉这个段闭包。
闭包嵌套
所以,性能上就不要发生闭包嵌套了。这更是一种性能无法忍受的问题