算法
背包问题递归解法
var selectMap = {};
const knapsack = (weights:number[], values:number[], total:number, w?:number) => {
if(w === undefined){
w = weights.length - 1;
}
if(total === 0 || w < 0){
return 0
}
var lastData = knapsack(weights, values, total, w - 1);
if(total < weights[w]){
return lastData;
}
var newData = knapsack(weights, values, total - weights[w], w - 1) + values[w];
if(lastData < newData){
selectMap[w] = true;
return newData;
}else{
selectMap[w] = false;
return lastData;
}
}
var ws = [2,2,6,5,4];
var vs = [6,3,5,4,6];
var ts = 16;
var totalWeight = 0;
var a = knapsack(ws,vs,ts);
console.log(selectMap)
Object.keys(selectMap).map(i => {
if(selectMap[i]){
totalWeight += ws[i];
console.log(`选择物品:${i};重量为:${ws[i]};价值为:${vs[i]}`);
}
});
console.log(`背包最大承重:${ts};实际重量:${totalWeight};最大价值:${a}`)
作用域
词法作用域 or 动态作用域
js 是词法作用域,就是说解释器引擎在解释 js 的时候,就已经确定作用域了,从下面的例子可以看出来:
function foo(){
// js 会输出 2
// 如果输出的是 3 就是动态作用域如 bash
console.log(a);
}
function bar(){
let a = 3;
foo();
}
let a = 2;
bar()
什么是作用域
作用域一般在前端指的是当前代码执行的上下文环境,这句话比较抽象,下面介绍几个概念。
- VO:变量对象
- AO:活动对象
- this:当前环境的 this 指向
- scope:指向父级作用域
变量对象可以理解为当函数还没有执行的时候,由于 js 有声明提前的概念,所以会有 VO 对象的概念,申请内存的时候先方进去,AO 是当代码执行的时候,就会将属于当前作用域的 VO 变为 AO。
this 是在函数执行的时候确定的。下周详细说一下 this
作用域类型
作用域大致分为:函数作用,全局作用域,块级作用域。
函数作用域:也称局部作用域,在函数大括号之间的内容就是该函数的作用域。
全局作用域:js 会有根对象,这个根对象提供一些除了语法之外的 API 让 js 的代码来调用,这个对象所处的环境就是全局作用域,比如 window。
块级作用域:js 是没有块级作用域的,并且有声明提前的概念,所以没有办法在 if 内声明一个变量。
作用域链
当函数内部想要使用一个变量时,这个时候会从当前作用域中寻到变量,如果不存在该变量,会到上一个作用域中寻找,所以变量间是有关系的,这个关系类似于 js 的原型链。子指向父的关系。小的作用域中的 scope 指向父级执行上下文。
这样作用域一层一层的关系就形成了作用域链,也就形成了变量逐级向上查找的关系,如果没有找到就会报一个错 变量is not defined
实例
var x = 10;
function foo() {
var y = 20;
function bar() {
var z = 30;
alert(x + y + z);
}
bar();
}
foo(); // 60
// 全局上下文的变量对象是
globalContext.VO === Global = {
x: 10
foo: <reference to function>
};
// 在“foo”创建时,“foo”的[[scope]]属性是
foo.[[Scope]] = [
globalContext.VO
];
// 在“foo”激活时(进入上下文),“foo”上下文的活动对象是
fooContext.AO = {
y: 20,
bar: <reference to function>
};
// “foo”上下文的作用域链为:
fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.:
fooContext.Scope = [
fooContext.AO,
globalContext.VO
];
// 内部函数“bar”创建时,其[[scope]]为:
bar.[[Scope]] = [
fooContext.AO,
globalContext.VO
];
// 在“bar”激活时,“bar”上下文的活动对象为:
barContext.AO = {
z: 30
};
// “bar”上下文的作用域链为:
barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.:
barContext.Scope = [
barContext.AO,
fooContext.AO,
globalContext.VO
];
// 对“x”、“y”、“z”的标识符解析如下:
- "x"
-- barContext.AO // not found
-- fooContext.AO // not found
-- globalContext.VO // found - 10
- "y"
-- barContext.AO // not found
-- fooContext.AO // found - 20
- "z"
-- barContext.AO // found - 30