leetcode(点燃木棒)

这篇博客探讨了一个类似图中寻找最短路径的问题,通过调整弗洛伊德算法来适应特殊情况,并使用BFS或DFS+记忆搜索优化。作者提供了将棍子编号转换为节点的方法,并展示了如何应用弗洛伊德算法来找出火柴棍之间的最短路径。代码实现包括了邻接矩阵的更新和最短路径的查找,最后从最长路径中找到可行解。
摘要由CSDN通过智能技术生成

一、问题

二、分析

这个跟在图上找寻每个节点到各个节点之间的最短路径相同,可以利用弗洛伊德算法,不过时间复杂度过高,为此由于问题的特殊性可以采用BFS获得DFS + 记忆搜索,这里只写出用弗洛伊德算法写出的代码。另外就是棍子编号和端点编号的转换问题,这个可以自己去推导,我直接写上了。

三、代码

	/**
	 * @param {number} height
	 * @param {number} width
	 * @param {number[]} indices
	 * @return {number[]}
	 */
	
	function getVeByStickNo(stick_no, width) {
		    let E_origin = stick_no % (2*width + 1);
		    let Layer = Math.floor(stick_no / (2*width + 1));
		    let v1 = 0;
		    let v2 = 0;
		    
		    if(E_origin - width < 0) { //横向的火柴棍
		        v1 = E_origin; v2 = v1 + 1;
		        v1 = v1 + Layer * (width + 1); v2 = v1 + 1;
		    } else { //纵向的火柴棍
		        v1 = E_origin - width; v2 = E_origin + 1;
		        v1 = v1 + Layer * (width + 1); v2 = v2 + Layer * (width + 1);
		    }
		    
		    return [v1,v2];
		}
		
		var lightSticks = function(height, width, indices) {
		    //弗洛伊德算法,相当于求每个节点之间的最短距离,然后选择最长节点中的最短节点
		    var v = [];
		    var e = [];
			var MAX = 99999;
			var ans = [];
		    
		    let v_count = (height + 1) * (width+1);
		    let e_count = (height * (width + 1)) + (width * (height + 1));
		    
		    for(let i = 0; i < v_count; i++) {
		        v[i] = 1;
		    }
	
		    for(let j = 0; j < v_count; j++) {
		        if(e[j] == undefined) {
	                e[j] = [];
	            }
		        for(let k = 0; k < v_count; k++) {
	                if(e[k] == undefined) { e[k] = [];}
		            if(k == (j + width + 1) 
	                || (k == (j + 1) && (Math.floor(k / (width+1)) == Math.floor(j / (width+1)))) 
	                || k == (j - width - 1) 
	                || (k == j - 1 && (Math.floor(k / (width+1)) == Math.floor(j / (width+1))))
	                ) {
	                    e[j][k] = e[k][j] = 1;
		            } else {
		                e[j][k] = e[k][j] = MAX;
		            }
		        }
		    }
		    
		    for(let u = 0; u < indices.length; u++) {
		        let t_v = getVeByStickNo(indices[u], width);
		        e[t_v[0]][t_v[1]] = e[t_v[1]][t_v[0]] = MAX;
		    }
	
	        for(let a = 0; a < v_count; a++) {
	            let top = a - width - 1;
	            let bottom = a + width + 1;
	            let right = a + 1;
	            let left = a - 1;
	            let count = 0;
	            if(e[a][top] == undefined || e[a][top] == MAX) {
	                count++;
	            }
	            if(e[a][bottom] == undefined || e[a][bottom] == MAX) {
	                count++;
	            }
	            if(e[a][right] == undefined || e[a][right] == MAX) {
	                count++;
	            }
	            if(e[a][left] == undefined || e[a][left] == MAX) {
	                count++;
	            }
	
	            if(count == 4) {
	                v[a] = 0;
	            }
	        }
	
		    let visited = [];
		    
		    
		    //邻接矩阵方法 时间复杂度高
		    let v_queue = [];
			v_queue.push(0);
			while(v_queue.length > 0) {
				let r_node = v_queue.pop();
				if(visited[r_node] != undefined) {
					continue;
				}
				visited[r_node] = 1;
	            v[r_node] = 0;
				for(let b = 0; b < e[r_node].length; b++) {
					if(e[r_node][b] == MAX || r_node == b) {
						continue;
					}
					for(let d = 0; d < e[r_node].length; d++) {
						e[d][b] = e[b][d] = Math.min(e[b][r_node] + e[r_node][d], e[b][d]);
						if(r_node != d) {
							e[d][r_node] = e[r_node][d] = Math.min(e[r_node][b] + e[b][d], e[r_node][d]);
						}
					}
					v_queue.push(b);
				}
			}
	
	        for(let a2 = 0; a2 < v.length; a2++) {
	            if(v[a2] > 0) {
	                return [];
	            }
	        }
			
	        let paths = [];
			for(let o = 0; o < e.length; o++) {
				let longestPath = 0;
				for(let p = 0; p < e[o].length; p++) {
	                if(e[o][p] >= MAX) {
	                    continue;
	                }
					longestPath = Math.max(e[o][p],longestPath);
				}
				if(longestPath != MAX && longestPath != 0) {
					if(paths[longestPath] == undefined) {
						paths[longestPath] = [];
					}
					paths[longestPath].push(o);
				}
			}
			
			if(paths.length > 0) {
				len_paths = Object.keys(paths);
				ans = paths[parseInt(len_paths[0])];
			}
	
			return ans;
		};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值