LeetCode热题100JS(64/100)第十二天|79|131|51|35|74
79. 单词搜索
题目链接:79. 单词搜索
难度:中等
刷题状态:1刷
新知识:
解题过程
思考
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 输出:true
没思路,看答案
题解分析
参考题解链接:79. 单词搜索(回溯,清晰图解)
详细分析如下
/**
* @param {character[][]} board
* @param {string} word
* @return {boolean}
*/
var exist = function(board, word) {
//定义函数dfs来判断是否有
function dfs(i,j,start){
//边界条件以及当前字符是否匹配,有一个不匹配的就返回错误
if(i<0||i>=board.length||j<0||j>=board[0].length||board[i][j]!=word[start]) return false
if(start==word.length-1) return true
//临时标记当前格子为访问过(避免重复使用)
let tmp=board[i][j]
board[i][j]=''
//遍历上下左右四个方向
let res=dfs(i+1,j,start+1)||dfs(i-1,j,start+1)||dfs(i,j+1,start+1)||dfs(i,j-1,start+1)
//恢复当前格子的的值
board[i][j]=tmp
return res
}
//遍历每个格子,尝试从每个格子开始搜索(不同的start)
for (let i=0;i<board.length;i++){
for(let j=0;j<board[0].length;j++){
if(dfs(i,j,0)) return true
}
}
return false
};
手搓答案(无非废话版)
/**
* @param {character[][]} board
* @param {string} word
* @return {boolean}
*/
var exist=function(board,word){
function dfs(i,j,start){
if(i<0||i>=board.length||j<0||j>=board[0].length||board[i][j]!=word[start]) return false
if(start==word.length-1) return true
let tmp=board[i][j]
board[i][j]=''
let res=dfs(i+1,j,start+1)||dfs(i-1,j,start+1)||dfs(i,j+1,start+1)||dfs(i,j-1,start+1)
board[i][j]=tmp
return res
}
for(let i=0;i<board.length;i++){
for(let j=0;j<board[0].length;j++){
if(dfs(i,j,0)) return true
}
}
return false
}
总结
注意边界条件的设置,一步一步来解就行
131. 分割回文串
题目链接:131. 分割回文串
难度:中等
刷题状态:2刷
新知识:
- `s.substring(start,end+1)` 用于提取字符串中部分内容的内置方法
解题过程
思考
示例 1:
输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]
题解分析
参考题解链接:【视频】回溯不会写?套路在此!(Python/Java/C++/Go/JS)
放下1刷过程
/**
* @param {string} s
* @return {string[][]}
*/
// var partition = function(s) {
// let n=s.length//3
// let res=[]//结果
// let path=[]//一条可行的路
// //这个函数判断字符串s从索引left到right的子串是否为回文
// //这里还是很好理解的
// function isPalindrome(s,left,right){
// while(left<right){
// if(s.charAt(left)!=s.charAt(right)){
// return false
// }
// left++
// right--
// //可以简写为如下,但我习惯上面的写法
// // if(s.charAt(left++)!=s.charAt(right--)){
// // return false
// // }
// }
// return true
// }
// // 上一个已经确定的回文子串的结束位置是 start
// // i表示当前考虑到字符串s中的第 i 个字符
// function dfs(start,i){
// if(i==n){
// //处理到最后一个字符了
// // path存储一下,再复制到res中
// res.push(path.slice())
// console.log('res',res)
// return
// }
// //下面这个是为了先找到s中最长的回文子串 aa,然后再一点点减小长度,直到出现最小单位的子串集,比如 a a b
// if(i<n-1){
// console.log('i<n-1',i)
// dfs(start,i+1)
// }
// console.log(start,i)
// console.log('isPalindrome(s,start,i)',isPalindrome(s,start,i))
// if(isPalindrome(s,start,i)){
// //是回文,加到path中
// path.push(s.substring(start,i+1))
// console.log('path',path)
// dfs(i+1,i+1)//下一个子串从i+1开始
// path.pop()//移除刚加入的子串,恢复现场
// }
// }
// dfs(0,0)
// return res
// };
var partition = function(s) {
let n=s.length
let res=[]
let path=[]
function isHuiwen(s,left,right){
while(left<right){
if(s.charAt(left++)!=s.charAt(right--)){
return false
}
}
return true
}
function dfs(start,i){
if(i==n){
res.push(path.slice())
return
}
if(i<n-1){
dfs(start,i+1)
}
if(isHuiwen(s,start,i)){
path.push(s.substring(start,i+1))
dfs(i+1,i+1)
path.pop()
}
}
dfs(0,0)
return res
}
手搓答案(无非废话版)
/**
* @param {string} s
* @return {string[][]}
*/
var partition=function(s){
let n=s.length
let path=[],res=[]
function isHuiwen(left,right){
while(left<right){
if(s[left]!=s[right]) return false
left++
right--
}
return true
}
function dfs(start){
if(start==n){
res.push([...path])
return
}
for(let end=start;end<n;end++){
if(isHuiwen(start,end)){
path.push(s.substring(start,end+1))
dfs(end+1)
path.pop()
}
}
}
dfs(0)
return res
}
总结
这里修改了dfs函数的逻辑,实现同样的效果
51. N 皇后
题目链接:51. N 皇后
难度:困难
刷题状态:1刷
新知识:
解题过程
思考
示例 1:
输入:n = 4 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。
没思路,看答案
题解分析
参考题解链接:【视频讲解】排列型回溯,简洁高效!(Python/Java/C++/C/Go/JS/Rust)
放下1刷过程
/**
* @param {number} n
* @return {string[][]}
*/
// var solveNQueens = function(n) {
// let res=[]
// // 存储每一行皇后的列位置,r行 col[r]列 [r,col[r]]是皇后的坐标
// let col=Array(n).fill(0)
// // 判断该列是否被用过
// let usedCol=new Array(n).fill(false)
// //该函数用来判断,对角线是否被占领
// function vaild(r,c){
// //r以上的行
// for(let R=0;R<r;R++){
// let C=col[R]
// //[R,C]是r以上的行的皇后的位置
// if (r+c==R+C||r-c==R-C) return false
// }
// return true
// }
// function dfs(r){
// //处理完最后一行了
// if(r==n){
// //生成棋盘表示
// let board=[]
// for(let c of col){
// board.push('.'.repeat(c)+'Q'+'.'.repeat(n-1-c))
// }
// res.push(board)
// return
// }
// //循环列,找到每行皇后可能在的列
// for(let c=0;c<n;c++){
// if(!usedCol[c]){
// if(vaild(r,c)){
// col[r]=c
// usedCol[c]=true
// dfs(r+1)
// usedCol[c]=false
// col[r]=0
// }
// }
// }
// }
// dfs(0)
// return res
// }
var solveNQueens = function(n) {
let res=[]
let col=new Array(n).fill(0)
let usedCol=new Array(n).fill(false)
function valid(r,c){
for(let R=0;R<r;R++){
let C=col[R]
if(R+C==r+c||R-C==r-c) return false
}
return true
}
function dfs(r){
if(r==n){
let board=[]
for(let c of col){
board.push('.'.repeat(c)+'Q'+'.'.repeat(n-1-c))
}
res.push(board)
return
}
for(let c=0;c<n;c++){
if(!usedCol[c]){
if(valid(r,c)){
col[r]=c
usedCol[c]=true
dfs(r+1)
usedCol[c]=false
col[r]=0
}
}
}
}
dfs(0)
return res
}
手搓答案(无非废话版)
/**
* @param {number} n
* @return {string[][]}
*/
var solveNQueens=function(n){
let res=[]
let col=new Array(n).fill(0)
let usedCol=new Array(n).fill(false)
function dfs(r){
if(r==n){
let board=[]
for(let c of col){
board.push('.'.repeat(c)+'Q'+'.'.repeat(n-1-c))
}
res.push(board)
return
}
for(let c=0;c<n;c++){
if(!usedCol[c]){
if(isnoX(r,c)){
col[r]=c
usedCol[c]=true
dfs(r+1)
usedCol[c]=false
col[r]=0
}
}
}
}
function isnoX(R,C){
for(let r=0;r<R;r++){
let c=col[r]
if(r+c==R+C||r-c==R-C) return false
}
return true
}
dfs(0)
return res
}
总结
注意 if(r+c==R+C||r-c==R-c) return false
- 这行代码检查当前行
r
的皇后位置(r, c)
是否与之前的某一行R
的皇后位置(R, col[R])
在同一条对角线上。 r + c == R + col[R]
检查两个皇后是否在同一主对角线(从左上到右下)。r - c == R - col[R]
检查两个皇后是否在同一副对角线(从右上到左下)。
35. 搜索插入位置
题目链接:35. 搜索插入位置
难度:简单
刷题状态:1刷
新知识:
解题过程
思考
示例 1:
输入: nums = [1,3,5,6], target = 5 输出: 2
题解分析
参考题解链接:画解算法:35. 搜索插入位置
详细分析如下
class Solution {
searchInsert(nums, target) {
let left = 0, right = nums.length - 1; // 初始化左右指针
while (left <= right) { // 当左指针小于等于右指针时继续循环
let mid = Math.floor((left + right) / 2); // 计算中间索引,使用 Math.floor 确保为整数
if (nums[mid] === target) { // 如果中间元素等于目标值
// 找到目标值,可以返回索引或进行其他逻辑处理
return mid;
} else if (nums[mid] < target) {
left = mid + 1; // 如果中间元素小于目标值,移动左指针
} else {
right = mid - 1; // 如果中间元素大于目标值,移动右指针
}
}
// 如果没有找到目标值,返回左指针作为插入位置
return left;
}
}
// 示例用法
const solution = new Solution();
const nums = [1, 3, 5, 6];
const target = 5;
console.log(solution.searchInsert(nums, target)); // 输出: 2
const target2 = 2;
console.log(solution.searchInsert(nums, target2)); // 输出: 1
const target3 = 7;
console.log(solution.searchInsert(nums, target3)); // 输出: 4
手搓答案(无非废话版)
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let left=0,right=nums.length-1
while(left<=right){
let mid=((right-left)>>1)+left
if(nums[mid]<target){
left=mid+1
}else{
right=mid-1
}
}
return left
};
总结
简单
74. 搜索二维矩阵
题目链接:74. 搜索二维矩阵
难度:中等
刷题状态:1刷
新知识:
解题过程
思考
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3 输出:true
没思路,看答案
题解分析
参考题解链接:两种方法:二分查找/排除法(Python/Java/C++/C/Go/JS/Rust)
详细分析如下
var searchMatrix = function(matrix, target) {
const m = matrix.length, n = matrix[0].length;
let left = -1, right = m * n;
while (left + 1 < right) {
const mid = Math.floor((left + right) / 2);
const x = matrix[Math.floor(mid / n)][mid % n];
if (x === target) {
return true;
}
if (x < target) {
left = mid;
} else {
right = mid;
}
}
return false;
};
手搓答案(无非废话版)
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var searchMatrix = function(matrix, target) {
let m=matrix.length,n=matrix[0].length
let left=0,right=m*n-1
while(left<=right){
let mid=((right-left)>>1)+left
M=matrix[Math.floor(mid/n)][mid%n]
if(M==target) return true
if(M<target){
left=mid+1
}else{
right=mid-1
}
}
return false
};
总结
注意这一行是怎么表示二维数组的位置M=matrix[Math.floor(mid/n)][mid%n]