题目描述:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
解题思路:
- 先查找path中的第一个字符的位置
- 这个位置可能有很多个,对每一个位置进行如下操作
- 在其周围查找下一个字符,同时将当前字符的位置信息存入数组中
- 如果步骤3查到了结果,查询结果是否在位置信息数组中,如果存在,退出当前循环,不存在,将结果存入数组,继续下下一个字符的查找
- 重复上述步骤5,直到所有循环结束。
code:
function hasPath(matrix, rows, cols, path)
{
let Arr = matrix.split('');
let charArr = new Array(rows);
//初始化二维数组
for(let i = 0 ; i < rows; i++ ){
charArr[i] = [];
}
//条件判断
if( matrix.length !== rows * cols ){
return false;
}
if(path.length > matrix.length){
return false;
}
//将初始值转换为二维数组
Arr.forEach((val,index)=>{
let y = Math.floor(index / cols);
let x = index % cols;
charArr[y][x] = val;
});
//判断节点{x,y}是否在arr中存在
function nodeExist(arr,{x,y}){
for( let i = 0 ; i < arr.length; i++ ){
if( arr[i].x === x && arr[i].y === y ){
return true;
}
}
return false;
}
//根据坐标,查找周围有没有指定的字符
/**
* function 根据坐标,查找周围有没有指定的字符
* @param {[type]} x [对应col]
* @param {[type]} y [对于row]
* @param {[type]} charIndex [查找字符的索引]
* @param {[type]} prevRes [上一次查找后的所有节点信息]
* @return {[type]} [true | false]
*/
let findNode = function(x,y,charIndex, prevRes){
let clone = [...prevRes];
let res = false;
if( charIndex < path.length){
if( x + 1 < cols){
if(hasNodeExist(x+1 ,y, charIndex, clone)){
return true;
}
}
if( x - 1 >= 0){
if(hasNodeExist(x-1 ,y, charIndex, clone)){
return true;
}
}
if( y+1 < rows ){
if(hasNodeExist(x ,y+1, charIndex, clone)){
return true;
}
}
if( y-1 >= 0 ){
if(hasNodeExist(x ,y-1, charIndex, clone)){
return true;
}
}
return false;
}else{
return true;
}
}
//第一个字符
let firstNode = path[0];
//在矩阵中查找第一个字符,并将结果保存起来
let firstNodeArr = [];
for(let i = 0 ; i < rows; i++){
for(let j = 0 ; j < cols; j++){
if(charArr[i][j] === firstNode ){
firstNodeArr.push({x:j, y:i});
}
}
}
/**
* function 判断在节点{x,y}是否存在charIndex位置的字符
* @param {[type]} x [col]
* @param {[type]} y [row]
* @param {[type]} charIndex [路径中的字符节点位置]
* @param {[type]} clone [先前节点的位子信息]
* @return {Boolean} [true | false]
*/
function hasNodeExist(x,y,charIndex,clone){
let char = path[charIndex];
if( charArr[y][x] === char ){
if( !nodeExist(clone, {x:x, y:y }) ){
clone.push({x:x, y:y });
res = findNode(x, y,charIndex+1, clone );
if(res === true){
return res;
}
}
}
return false;
}
//记录路径节点的结果
let res = [];
if(firstNodeArr.length === 0){
return false;
}else{
for(let i = 0 ; i < firstNodeArr.length; i++){
//从该节点开始,寻找下一个节点
let item = firstNodeArr[i];
let res = findNode(item.x, item.y, 1, [{x:item.x, y:item.y}]);
if(res){
return true;
}
}
return false;
}
}