堆 heap, 准备博客参考

那个概率越乘越小,但是这个路径是累加的效果,到达当前节点目前最大,不代表它就是最大的路径。

但是,如果当前节点是距离最小的,它一定就是最小了。

也就是能应用迪特斯特拉算法思想,其实是贪心思想的,面临选择的时候,选择它,它一定是最佳的。

如果是求最短路径

var maxSum = function(nums1, nums2) {
let n12 = [...new Set([...nums1.concat(nums2)])];
console.log('n12: ',n12)
let n12l = n12.length;

let s1 = nums1[0],
s2 = nums2[0],
r1 = nums1[nums1.length-1],
r2 = nums2[nums2.length-1],
s1Index = n12.indexOf(s1),
s2Index = n12.indexOf(s2),
r1Index = n12.indexOf(r1),
r2Index = n12.indexOf(r2);
let e1 = [],
e2 = [];
nums1.forEach((n1, i)=>{
if(nums1[i+1] !== undefined)
e1.push([n1, nums1[i+1]]);
})
nums2.forEach((n1, i)=>{
if(nums2[i+1] !== undefined)
e1.push([n1, nums2[i+1]])
})
let e12 = e1.concat(e2);
let len = n12.length;
let nl = n12.length;
let paths = [];
while(nl--){
paths[nl] = []
}
// for(let i=0;i< n12.length; i++){
// paths.set(n12[i], [])
// }
let edges = [];
let succProb = [];
e12.forEach(([s, e])=>{
let sI = n12.indexOf(s),
eI = n12.indexOf(e),
w = s+e;
// s-e 的权重 w
paths[sI].push([eI, w]);
paths[eI].push([sI, w]);
edges.push([sI, eI])
succProb.push(w)
})
// let succ = [];
// // dfs
// let st = [nums1[0]];
// let map = new Map();
// while(st.length){
// let n = st.shift();
// if(map.get(n)) continue;
// map.set(n, true)
// let ps = paths[n];
// for(let i=0; i<ps.length; i++){
// let n1 = ps[i];
// if(map.get(n1)) continue;
// succ.push(n+n1)
// }
// }
let mod = 10**9 + 7;

// const getCount = (s, e)=>{
// let dp = new Array(n12l).fill(0);
// dp[s] = 10**7;
// while(true){
// let k = false;
// for(let j=0; j<edges.length; j++){
// if(dp[edges[j][0]] + succProb[j] > dp[edges[j][1]]){
// dp[edges[j][1]] = dp[edges[j][0]] + succProb[j];
// k = true;
// }
// if (dp[edges[j][1]] + succProb[j] > dp[edges[j][0]]) {
// dp[edges[j][0]] = dp[edges[j][1]] + succProb[j];
// k = true;
// }
// }
// if(!k) break;
// }
// return dp[e]
// }
// Dijkstra每次选距离最小的点,是一种贪心决策。从源点出发时,也必须挑选最短点。eg:d(0-c)>d(0-a)+d(a-c),所以初始c点时不能进入S集合的。
const getCount = (s, e)=>{
let v = new Array(n12l).fill(false);
let stack = [[s, 0]];
while(stack.length){
console.log('stack: ',JSON.stringify(stack))
let [n, weight] = stack.shift();
if(v[n]) continue
v[n] = true;
if(n===e) return weight;
let ps = paths[n];
for (let i = 0; i < ps.length; i++) {
let [nn, nw] = ps[i];
if(v[nn]) continue;
let f = 0;
if(n!==s){
// 这个权限是2点的和,会重复累加,所以要减去
f = n12[n]
}
stack.push([nn, (weight+nw-f)%mod]);

// 这个应该是从小到大,虽然从大到小测试用例也一样,纯属巧合
stack.sort((a, b)=>a[1]-b[1])
}
}

}
let res1 = 0,
res2 = 0,
res3 = 0,
res4 = 0;
res1 = getCount(s1Index, r1Index);
res2 = getCount(s1Index, r2Index);
res3 = getCount(s2Index, r1Index);
res4 = getCount(s2Index, r2Index);
// 2数组之间可能没有交集
// res1 = res1 === undefined? 0: res1;
// res2 = res2 === undefined? 0: res2;
// res3 = res3 === undefined? 0: res3;
// res4 = res4 === undefined? 0: res4;
console.log(res1, res2, res3, res4)

return Math.max(res1, res2, res3, res4)
};

let nums1 = [1,4,5,8,9,11,19], nums2 = [2,3,4,11,12];

console.log(maxSum(nums1, nums2))

// 最小距离

// console.log(res1, res2, res3, res4)

// 35 28 39 32

 

 下面这2个实现堆都是从数组索引0开始,

 
实现大顶堆的过程是往空数组里面push对象,然后是从树的角度从下到上构建大顶堆,只要新添加的对象值>它的父节点(Math.floor((i-1)/2))的值,便交换,一直交换下去,知道堆顶。
取数据时,弹出数组中的第一个,再把数组中最后一个放到数组中第一位,然后比较从上到下从数组第0个开始比较它的2个子节点(2*i+1和 2*i+2),并交换,直到不存在交换条件为止。
 
而我们初始想的是,再形成最大堆时,连续push多个对象,然后形成一个最大堆https://segmentfault.com/a/1190000015487916,这样应该会做很多无用的操作,除了从下到上的堆形成,还又从左到右遍历数组比较树的子节点。这个实现堆的原理是优先选定初始点,然后从下到上,从左到右形成堆。
 
把优先队列写写,再写点理解,再把答案写上。

 

posted @ 2020-08-04 08:21  土豆zhang  阅读(144)  评论(0编辑  收藏  举报