计划:算法只刷codeTop前端部分前60题与一些补充题
场景手撕根据后续题单刷
全部题目都是最简单好记的最优解法
day4 共8道力扣
/**
* @param {string} num1
* @param {string} num2
* @return {string}
*/
var addStrings = function(num1, num2) {
//字符串相加,最后以字符串返回
//一位一位地截取?不,截取确定不了位数关系,还是考虑直接换成数组来存储
//设置进位符来记忆
let m = num1.length-1;
let n = num2.length-1;
let flag = 0;
//结果存放的数组
const ans = [];
//列竖式的思路,从个位开始计算,最后reverse翻转
while(m>=0||n>=0||flag!==0){
//当更高位数还有计算时
//获取当前同一位置的每一位
//注意 字符串中获取某一位,使用charAt,转换为数字来计算,还需要-'0'
//也可以直接通过下标来[]
let n1 = m>=0?num1.charAt(m)-'0':0;
let n2 = n>=0?num2[n]-'0':0;
let sum = n1+n2+flag;
if(sum>=10){
//不能ans[],因为不知道m和n的大小-不知道根据哪个来判断位数来存放
//所以使用push来放在最新的位置
ans.push(sum%10);
flag = 1;
}else{
ans.push(sum);
flag = 0;
}
//移动位置
m--;n--;
}
//join('')是数组方法,用来把数组的所有元素按指定分隔符连接成一个字符串。join()默认用,来分隔;''表示空字符串来分隔
return ans.reverse().join('');
};
/**
* @param {string} version1
* @param {string} version2
* @return {number}
*/
var compareVersion = function(version1, version2) {
//版本号由.分开,前导0忽略-parseInt转换为整数
//不够的位次用0来补充
let v1 = version1.split('.');
let v2 = version2.split('.');
const m = v1.length;
const n = v2.length;
for(let i = 0;i<m||i<n;i++){
//只要其中一个没处理完,都接着处理;不够位次的就变为0
let letter1 = i>=m?0:parseInt(v1[i]);
let letter2 = i>=n?0:parseInt(v2[i]);
if(letter1>letter2)return 1;
else if(letter2>letter1)return -1;
}
return 0;
};
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
//O(log n) 时间复杂度-二分查找
let left = 0;
let right = nums.length-1;
while(left<=right){
let mid = Math.floor(left+(right-left)/2);
if(nums[mid]===target)return mid;
else if(nums[mid]>target){
right = mid-1;
}else if(nums[mid]<target){
left = mid+1;
}
}
return -1;
};
/**
* @param {number} n
* @return {string[]}
*/
var generateParenthesis = function(n) {
//左括号数量一定大于右括号数量
//选与不选来回溯
const ans = [];
const path = new Array(n*2);
dfs(0,0);
return ans;
function dfs(a,b){
//a为左括号数量,b为右括号数量
//生成完的情况
if(b === n){
ans.push(path.join(''));
return ;
}
//可以放入左括号
if(a<n){
path[a+b] = '(';
dfs(a+1,b);
}
//可以放入右括号
if(b<a){
path[a+b] = ')';
dfs(a,b+1);
}
}
};
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
//动态规划dp数组
//const dp = new Array(n).fill(0);
const dp = [];
dp[1] = 1;
dp[2] = 2;
for(let i = 3;i<=n;i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
};
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {boolean}
*/
var hasPathSum = function(root, targetSum) {
//根节点到叶子节点路径val相加为targetSum
//剪枝:若是还没到叶子就已经很大,直接返回
if(!root)return false;
//递归,边界条件为到叶子
if(!root.left&&!root.right){
return root.val===targetSum;
}
//进入递归主体
return hasPathSum(root.left,targetSum-root.val)||hasPathSum(root.right,targetSum-root.val);
};
/**
* @param {string} s
* @return {string[]}
*/
var restoreIpAddresses = function(s) {
//ip地址:当前处理的位置 已完成的分割数量 当前的数值
const n = s.length;
const ans = [];
//截断的位置
const dot = new Array(4);
dfs(0,0,0);
return ans;
function dfs(i,j,val){
//已经完成截断
if(i === n && j === 4){
//通过dot来判断末尾位置
const [a,b,c,_] = dot;
ans.push(`${s.slice(0,a)}.${s.slice(a,b)}.${s.slice(b,c)}.${s.slice(c)}`);
return ;
}
//剪枝,三种情况
if(i === n)return ;
if(j === 4)return ;
//数值超过255了
val = val*10+parseInt(s[i]);
if(val>255)return ;
//普通情况,进行分割或者不分割。为0肯定直接分割
//不分割的情况
if(val>0){
dfs(i+1,j,val);
}
//分割
//记录这一段的dot位置-注意是这一段完整了的当前下标位置
dot[j] = i+1;
dfs(i+1,j+1,0);
}
};
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var maxDepth = function(root) {
//递归,左子树右子树
//先判空
if(!root)return 0;
//对左右子树进行分别操作
const leftDepth = maxDepth(root.left);
const rightDepth = maxDepth(root.right);
//返回的时候进行数字的计算,加上当前这个层数1
return Math.max(leftDepth,rightDepth)+1;
};