【JS算法题LeetCode】含思路+详细注释,适合零基础算法小白,持续更新中......

JS算法题,LeetCode

前端JS算法题个人练习记录,含思路+详细注释,适合零基础算法小白。



提示:以下是本篇文章正文内容,下面代码可供参考

一、LeetCode

001.两数之和

https://leetcode.cn/problems/two-sum/description/

1.创建map
2.遍历数组
3.定义差,target-nums[i]
4.如果map.has(差),返回[i, map.get(差)]
else,map.set(值,索引)

5.全不符,直接return[]

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
 var twoSum = function(nums, target) {
    // 新建map
    const map = new Map()
    // 遍历num数组
    for(let i = 0; i < nums.length; i++){
        // 定义 差
        const complement = target - nums[i]
        // 如果map里面有nums[i]对应的差
        if(map.has(complement)){
            // 返回 差的索引and和数组索引i
            return [map.get(complement),i]
        // 如果map里面没nums[i]对应的差
        }else{
            // 将nums[i]和数组索引i放进map中
            map.set(nums[i],i)
        }
    }
    // 如果遍历完nums数组,仍然没有,即返回一个空数组
    return []
};

002.两数相加

https://leetcode.cn/problems/add-two-numbers/description/

1.新建dummy节点为空,curr指针指向dummy,设置进位carry为0
2.只要l1和l2其中有一个链表不为空,定义两数之和sum
如果l1不为空,sum+l1的值,l1进一位;l2同理
最终sum是2个链表数之和**(sum)+进位(carry)**
curr指向新建一个节点,值为sum取模10;计算进位carry,除于10再floor向下舍
指针指向下一个节点
3.最后检查carry,如果carry>0,即需要新增一个节点来放carry的值
4.返回dummy.next

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
 var addTwoNumbers = function(l1, l2) {
    // 定义链表头,dummy为空节点
    let dummy = new ListNode()
    // 指针指向链表头
    let curr = dummy
    // 设置进位carry
    let carry = 0

    // 只要l1和l2其中有一个链表不为空,就一直执行
    while(l1 !== null || l2 !== null){
        // 两数相加之和
        let sum = 0
        // 如果l1不为空
        if(l1 !== null) {
            // sum加上l1的值
            sum += l1.val
            // l1要进一位
            l1 = l1.next
        }
        // 如果l2不为空
        if(l2 !== null) {
            // sum加上l2的值
            sum += l2.val
            // l2要进一位
            l2 = l2.next
        }
        // 最终sum是 2个链表数之和+进位
        sum += carry
        // curr指向新建一个节点,值为sum取模10,12 % 10 = 2
        curr.next = new ListNode(sum % 10)
        // 计算进位carry,除于10再floor向下舍
        carry = Math.floor(sum / 10)
        // 指针指向下一个节点
        curr = curr.next
    }
    // 最后检查carry,如果carry>0,即需要新增一个节点来放carry的值
    if(carry > 0){
        curr.next = new ListNode(carry)
    }
    // 返回头节点,即dummy.next
    return dummy.next
};

003.无重复字符的最长子串

https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/

1.创建set,定义双遍历指针 i 和 j 都为0
2.定义无重复字符串最大长度maxLength为0,遍历字符串
3.如果set里没有s[i],即没有重复过的字符
将s[i]添加进set,并更新maxLength的值,取maxLength和set.size的max值
4.如果set还有set,
while循环确保set不存在s[i]
删除s[j],即第一次出现的重复值,并将j++指向下一个值
再将s[i]加入set里
5.返回maxLength

/**
 * @param {string} s
 * @return {number}
 */
 var lengthOfLongestSubstring = function(s) {
    // 新建set
    const set = new Set()
    // 双指针,滑动窗口思想,i是遍历指针,j是指向字符串s的开头
    let i = 0, j = 0, maxLength = 0
    // 遍历字符串
    for(i = 0; i < s.length; i++){
        // 如果set里没有s[i],即没有重复过的字符
        if(!set.has(s[i])){
            // 添加进set
            set.add(s[i])
            // 更新无重复字符的最长子串的值
            maxLength = Math.max(maxLength, set.size)
        }else{
            // 只要set里还有s[i]
            // 这里要用while,确保set里不存在s[i]
            while(set.has(s[i])){
                // 删除s[j],即第一次出现的重复值
                set.delete(s[j])
                // 将j指向下一个值
                j++
            }
            // 再将s[i]加入set里
            set.add(s[i])
        }
    }
    // 返回无重复字符的最长子串的值
    return maxLength
};

005.最长回文子串

https://leetcode.cn/problems/longest-palindromic-substring/

1.如果字符串长度小于2,直接返回自身
2.创建start为0,即最长回文子串的起始位置;创建最大长度maxLength为1
3.定义中心扩展算法(left,right)双指针
只要当左右指针都不越界,且左右字符都相等
如果s内的长度(right - left + 1)> maxLength,即在s内找到了更大的回文子串
更新maxLength的值为s的长度,更新start = left
双指针变动,left-- right++
4.遍历字符串s,考虑到两种情况
i-1,i+1
i, i+1
5.返回s.substring(start, start + maxLength)

/**
 * @param {string} s
 * @return {string}
 */
 var longestPalindrome = function(s) {
    // 如果字符串长度小于2,即为a这种,直接返回自身即可
    if(s.length < 2){
        return s
    }
    // 设置start,即最长回文字符串的起始位置
    let start = 0
    // 设置最长回文字符串的长度
    let maxLength = 1
    // expandAroundCenter中心扩展算法
    function expandAroundCenter(left, right){
        // 只要当左右都不越界,且左右字符相等时
        while(left >= 0 && right < s.length && s[left] === s[right]){
            // 如果s内的长度大于maxLength,即在s内找到了更大的回文子串
            if(right - left + 1 > maxLength){
                // 更新maxLength长度
                maxLength = right - left + 1
                // 更新start起始位置
                start = left
            }
            // 中心扩展
            left--
            right++
        }
    }
    for(let i = 0; i < s.length; i++){
        // abcba,c为中心
        expandAroundCenter(i-1, i+1)
        // abba,中心在b之间
        expandAroundCenter(i, i+1)
    }
    // 返回最长回文字符串
    return s.substring(start, start + maxLength)
};

015.三数之和

https://leetcode.cn/problems/3sum/description/

1.定义result数组
2.给nums数组升序排序
3.遍历nums数组,从0至length-2,三指针注意边界
i是遍历指针,i是第一个元素时或新的数与之前的数不相等时,再进行判断,即跳过相同的数(不进行判断)
start = i + 1, end = length - 1,只要start < end
如果三数相加等于0,将三数push进result数组内,start++,end–
确保结果数组里不出现重复,只要start[i]===[i-1],start++
4.三数之和小于0,找更大的值,start++
5.三数之和大于0,找更小的值,end–

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
 var threeSum = function(nums) {
    // 返回的结果
    const result = []
    // 给nums数组升序排序
    nums.sort(function(a, b) {
        return a - b
    })
    // 遍历nums数组,由于三指针,注意边界
    for(let i = 0; i < nums.length-2; i++){
        // i为第一个元素时或新的数与之前的数不相等时,再进行判断;
        // 即跳过相同的数,不进行判断
        if(i === 0 || nums[i] !== nums[i-1]){
            // 三指针
            let start = i + 1
            let end = nums.length - 1
            // 只要start不等于end
            while(start < end){
                // 如果三数相加等于0
                if(nums[i] + nums[start] + nums[end] === 0){
                    // 将三数放进结果数组里
                    result.push([nums[i],nums[start],nums[end]])
                    start++
                    end--
                    // 确保结果数组里不出现重复
                    while(start < end && nums[start] === nums[start - 1]){
                        start++
                    }
                // 三数之和小于0,找更大的值
                }else if (nums[i] + nums[start] + nums[end] < 0){
                    start++
                // 三数之和大于0,找更小的值
                }else if (nums[i] + nums[start] + nums[end] > 0){
                    end--
                }
            }
        }
    }
    return result
};

019.删除链表的倒数第N个节点

https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

1.创建dummy空节点,dummy指向head
2.双指针start和end都指向dummy,遍历n控制end和start的身位,i<=n
3.只要end不为空,end.next;start.next
4.删除节点start.next=start.next.next
5.return dummy.next

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
 var removeNthFromEnd = function(head, n) {
    // 定义链表头,dummy为空节点
    let dummy = new ListNode()
    // 让dummy指向head
    dummy.next = head
    // 设置双指针,利用滑动窗口,定位到倒数第n个节点
    let start = dummy
    let end = dummy

    // 让end指针与start指针间隔n+1个位置
    // i<=n,即end !== null
    // i<n,即end.next !== null
    for(let i = 0; i <= n; i++){
        end = end.next
    }
    // 只要end节点不为空,就让双指针继续挪动
    while(end !== null){
        start = start.next
        end = end.next
    }
    // end为空时,start节点在要删除的节点的前一个位置
    // 直接将指针跳过要删除的节点,指向它的next
    start.next = start.next.next
    // 返回头节点
    return dummy.next
};

020.有效的括号

https://leetcode.cn/problems/valid-parentheses/

1.new Map存set括号,k是左括号,v是右括号
2.new Array当stack,遍历字符串s
map里有没有这个k,有的话把v push进stack;
map里没有这个k,比较s[i]和stack.pop,不一样false

3.如果map.has(s),即Map里有s[i]这个k,即左括号,将对应的右括号存入stack
4.如果Map里没有s这个k,即右括号,比较s[i]和stack.pop是不是一样。不一样return false
5.遍历完s,看stack是否为空,不为空false;
6.最后return true

/**
 * @param {string} s
 * @return {boolean}
 */
 var isValid = function(s) {
    // 定义一个map来放配对的括号
    const mapping = new Map()
    mapping.set('(',")")
    mapping.set('[',"]")
    mapping.set('{',"}")
    // 定义一个数组作为栈
    const stack = []
    // 遍历字符串
    for(let i = 0; i < s.length; i++){
        // 如果Map里有s[i],即s[i]是左括号
        if(mapping.has(s[i])){
            // 将Map里s[i]对应的右括号push进栈
            stack.push(mapping.get(s[i]))
        // 如果Map里没有s[i],即s[i]是右括号
        }else{
            // 如果pop出栈的不是s[i]
            if(stack.pop() !== s[i]){
                // 不符合有效括号集定义
                return false
            }
        }
    }
    // 如果栈不为空,即还有剩余的括号
    if(stack.length !== 0){
        // 不符合有效括号集定义
        return false
    }
    // 排除万难,即符合定义
    return true
};

021.合并两个有序链表

https://leetcode.cn/problems/merge-two-sorted-lists/description/

1.创建空链表curr,dummy指向curry
2.只要l1和l2都不为空,while每次都curr.next
3.如果l1<l2,curr指向l1且l1.next;else curr指向l2且l2.next

4.如果剩下的l1不为空,全指向l1;l2同理
5.return dummy.next

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
 var mergeTwoLists = function(list1, list2) {
    // 创建一个空结点curr作为新链表
    let curr = new ListNode()
    // 让dummy指向curr
    let dummy = curr

    // 只要l1和l2都不为空
    while(list1 !== null && list2 !== null){
        // 如果l1的值<l2
        if(list1.val < list2.val){
            // curr指向l1
            curr.next = list1
            // l1进一步
            list1 = list1.next
        // 如果l2的值<l1
        }else{
            // curr指向l2
            curr.next = list2
            // l2进一步
            list2 = list2.next
        }
        // curr进一步
        curr = curr.next
    }
    // 如果l1还有剩余
    if(list1 !== null){
        // curr直接指向l1
        curr.next = list1
    }
    // 如果l2还有剩余
    if(list2 !== null){
        // curr直接指向l2
        curr.next = list2
    }
    // 返回链表dummy.next
    return dummy.next
};

024.两两交换链表中的节点

https://leetcode.cn/problems/swap-nodes-in-pairs/description/

1.创建空节点dummy指向head,创建遍历指针curr指向dummy
2.只要curr后还有2个节点不为空
3.定义n1和n2,分别是curr的下一个节点和下下个节点
4.curr.next; n1.next ; n2.next
5.curr指向n1,此时n1和curr已经隔着一个节点了
6.return dummy.next

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
 var swapPairs = function(head) {
    // 创建空节点dummy
    let dummy = new ListNode()
    // 让dummy节点指向head
    dummy.next = head
    // 定义遍历指针curr
    let curr = dummy
    // 只要curr后还有两个节点不为空
    while(curr.next !== null && curr.next.next !== null){
        //定义n1,即curr的下一个节点
        let n1 = curr.next
        //定义n2,即curr的下下一个节点
        let n2 = curr.next.next
        // curr n1 n2,按照顺序找到next
        curr.next = n2
        n1.next = n2.next
        n2.next = n1
        // 将curr指向n1,此时n1和curr已经隔着1个节点了
        curr = n1
    }
    // 返回交换后的链表头节点
    return dummy.next
};

049.字母异位词分组

https://leetcode.cn/problems/group-anagrams/description/

1.检查数组是否为空,若为空返回空数组
2.创建map,k为含26个字母的数组转换的字符串,v为数组(不同的字母异位词)
characters是含26个字母的空数组[0,…,0]; ascii是字母的索引(a为97);characters[ascii]是字母出现的次数
3.遍历strs数组,定义characters
4.遍历str字母,定义每个字母的ASCII - 97,让数组内字母出现的次数+1
5.定义key,将characters用’-'join成独一无二的字符串
6.如果map里面有k,展开运算符将str追加进map.get(k);没有k,直接将str加入v
7.遍历map,将map中的v返回给一个数组,并返回该数组作为结果

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
 var groupAnagrams = function(strs) {
    // 判断字符串是否为空
    if(strs.length === null){
        // 如果为空,返回空数组
        return []
    }
    // 创建map,k为含26个字母的数组转换的字符串,v为数组(不同的字母异位词)
    const map = new Map()
    // 遍历字符串strs中的每个元素str
    for(const str of strs){
        // 定义含26个字母的空数组(作为map的key)
        // ES6新方法,Array(数量).fill(填充内容)
        const characters = Array(26).fill(0)
        // 遍历每个str的字母
        for(let i = 0; i < str.length; i++){
            // 定义每个字母的ASCII码,并且a为97,使得从0开始,作为characters的索引
            const ascii = str.charCodeAt(i) - 97
            // 让数组内对应的索引的值+1,默认为全0,例如b出现一次,即characters[2] = 0+1
            characters[ascii]++
        }
        // 将含26个字母的数组转换的字符串,且用-连接,确保独一无二
        const key = characters.join('-')
        // 如果map里面有k,如已有tea,又来eat
        if(map.has(key)){
            // 将str追加入对应k的v中
            // ES6新方法,...展开运算符
            map.set(key, [...map.get(key), str])
        // 如果map里面没有k
        }else{
            // 将str加入对应k的v中
            map.set(key, [str])
        }
    }
    // 遍历map,将v返回给一个数组
    const result = []
    for(const arr of map){
        // 将map里的v,push进result数组
        // arr[0]代表k,arr[1]代表v
        result.push(arr[1])
    }
    // 返回结果
    return result
};

053.最大子数组和

https://leetcode.cn/problems/maximum-subarray/description/

1.创建新数组memo,表示最大和的子数组
2.第一个值nums[0],直接赋给memo和max
3.遍历nums数组,从1开始,用Math.max()
比较旧数组+新元素单独成一个数组的和新元素单独成一个数组的大小
memo[i - 1] + nums[i], nums[i]
比较maxmemo[i]的大小
4.返回max

/**
 * @param {number[]} nums
 * @return {number}
 */
 var maxSubArray = function(nums) {
    // 创建新数组
    const memo = []
    // 第一个值直接赋给数组
    memo[0] = nums[0]
    // 让最大值为第一个数
    let max = nums[0]

    // 遍历nums数组,从第一个开始
    for(let i = 1; i < nums.length; i++){
        // 判断保留旧数组,还是让新元素单独成一个数组
        // 比较旧数组+新元素单独成一个数组和新元素单独成一个数组的大小
        // nums[i]新元素单独成一个数组
        // memo[i]最大数组
        // memo[i - 1]最大旧数组
        memo[i] = Math.max(memo[i - 1] + nums[i], nums[i])
        // 判断max和memo[i]谁比较大
        max = Math.max(max, memo[i])
    }

    // 返回最大值
    return max
};

054.螺旋矩阵

https://leetcode.cn/problems/spiral-matrix/description/

1.判空,返回空数组
2.定义上下左四个边界、方向(顺时针:下左上)、结果数组
3.只要左 <= 右 且 上 <= 下
如果方向为右,遍历向右行,左到右,i++,push值matrix[top][i],top++,方向改为下
如果方向为下,遍历向下行,上到下,i++,push值matrix[i][right],right–,方向改为左
如果方向为左,遍历向左行,右到左,i–,push值matrix[bottom][i],bottom–,方向改为上
如果方向为上,遍历向上行,下到上,i–,push值matrix[i][left],left++,方向改为右

/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
 var spiralOrder = function(matrix) {
    // 空数组直接返回空数组
    if (matrix.length === 0) {
        return []
    }
    // 定义上下左右四个边界
    let top = 0
    let bottom = matrix.length - 1
    let left = 0
    let right = matrix[0].length - 1

    // 定义方向,顺时针,右下左上
    let direction = "right"
    // 定义结果数组
    let result = []

    // 只要左<=右且上<=下
    while (left <= right && top <= bottom) {
        if(direction === "right"){
            // 遍历向右行,left到right
            for(let i = left; i <= right; i++){
                // 将值push进结果数组
                result.push(matrix[top][i])
            }
            // 走完了top一层
            top++
            // 改变方向,向下
            direction = "down"
        }else if (direction === "down"){
            // 遍历向下行,top到bottom
            for(let i = top; i <= bottom; i++){
                // 将值push进结果数组
                result.push(matrix[i][right])
            }
            // 走完了right一层
            right--
            // 改变方向,向左
            direction = "left"
        }else if (direction === "left"){
            // 遍历向左行,right到left
            for(let i = right; i >= left; i--){
                // 将值push进结果数组
                result.push(matrix[bottom][i])
            }
            // 走完了bottom一层
            bottom--
            // 改变方向,向上
            direction = "top"
        }else if (direction === "top"){
            // 遍历向上行,bottom到top
            for(let i = bottom; i >= top; i--){
                // 将值push进结果数组
                result.push(matrix[i][left])
            }
            // 走完了left一层
            left++
            // 改变方向,向右
            direction = "right"
        }
    }
    // 返回结果
    return result
};

055.跳跃游戏

https://leetcode.cn/problems/jump-game/description/

Greedy贪心算法
1.定义最大跳数maxJump为 长度-1
2.从后往前遍历数组,且从倒数第二个开始第一个
如果 索引+值 >= maxJump,是个通的点
更新最大跳数到通的点
3.如果maxJump为0,返回true

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function (nums) {
    // Greedy贪心算法
    // 定义最大跳数为长度-1
    let maxJump = nums.length - 1
    // 从后往前遍历数组,且从倒数第二个开始至第一个
    for (let i = nums.length - 2; i >= 0; i--) {
        // 如果索引+值大于等于最大跳数,是个通的点
        if (i + nums[i] >= maxJump) {
            // 更新最大跳数到通的点
            maxJump = i
        }
    }

    // 如果maxJump为0,返回true
    return maxJump === 0
};

DP:动态规划(从下往上),递归的表是从后往前推
1.定义数组nums长度totalLength,创建记忆数组memo存放状态:0未知,1通,-1不通,最后一位肯定是通
2.从后往前遍历,从倒数第二个至第0个
最大跳数maxJump,当前位置+可以跳跃的最大值最后一位 取小值
3.从前往后遍历,从下一个i+1至最大跳数maxJump
如果任何一个后面的点是通的,即前面的往后遍历发现后面的j为1,就把前面的i也改为1break
4.如果第一个数如果为通,则顺利回到最开始,即成功

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function (nums) {
    // Greedy贪心算法
    // 定义最大跳数为长度-1
    let maxJump = nums.length - 1
    // 从后往前遍历数组,且从倒数第二个开始至第一个
    for (let i = nums.length - 2; i >= 0; i--) {
        // 如果索引+值大于等于最大跳数,是个通的点
        if (i + nums[i] >= maxJump) {
            // 更新最大跳数到通的点
            maxJump = i
        }
    }

    // 如果maxJump为0,返回true
    return maxJump === 0
};

056.合并区间

https://leetcode.cn/problems/merge-intervals/description/

1.判空或1个元素,返回原数组
2.数组sort升序,按照元素第一位数
3.定义curr指针为第1个元素和结果数组
4.for of遍历数组,可以合并的情况,即curr的终止位置>interval的起始位置,将curr的终止位置更新取大值
不可以合并的情况,将前一个合并后的数组curr推进结果指针指向interval继续遍历
5.如果最后一位是可以合并的情况,需要push
6.返回结果数组

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function (intervals) {
    // 如果长度为0或只有1个
    if (intervals.length < 2) {
        return intervals
    }
    // 按照数组第一位数排序
    intervals.sort(function (a, b) {
        return a[0] - b[0]
    })
    // 定义指针
    let curr = intervals[0]
    // 定义结果数组
    let result = []
    // 遍历intervals数组
    for (let interval of intervals) {
        // 可以合并的情况,即curr的终止位置>interval的起始位置
        if (curr[1] >= interval[0]) {
            // 将curr的终止位置更新,取大值
            curr[1] = Math.max(curr[1], interval[1])
        // 不可以合并的情况
        }else{
            // 将前一个合并后的数组push进结果
            result.push(curr)
            // 指针指向interval继续遍历
            curr = interval
        }
    }
    // 如果最后一位是可以合并的情况,需要push
    if(curr.length !== 0){
        result.push(curr)
    }
    // 返回结果
    return result
};

062.不同路径

https://leetcode.cn/problems/unique-paths/description/

1.创建memo二维数组
2.第一列和第一行的所有格子的不同路径数都只有1条
填充第一列为1;填充第一行为1
4.遍历memo二维数组,新格子的不同路径数 = 左边格子和上边格子路径数之和
6.返回结果,注意索引要-1

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function (m, n) {
    // 创建memo数组
    const memo = []
    // 二维memo数组
    for (let i = 0; i < n; i++) {
        memo.push([])
    }
    // 第一列和第一行的路径只有1条
    // 填充第一列为1
    for (let row = 0; row < n; row++) {
        memo[row][0] = 1
    }
    // 填充第一行为1
    for (let col = 0; col < m; col++) {
        memo[0][col] = 1
    }
    // 遍历memo二维数组
    for (let row = 1; row < n; row++) {
        for (let col = 1; col < m; col++) {
            // 新格子的不同路径数 = 左边格子和上边格子路径数之和
            memo[row][col] = memo[row - 1][col] + memo[row][col - 1]
        }
    }
    // 返回结果,索引要-1
    return memo[n-1][m-1]
};

066.加一

https://leetcode.cn/problems/plus-one/description/

1.从右往左遍历digits数组
2.如果元素不是9,首先是最右边的个位,加1返回数组
元素是9,即个位是9,仅需将个位设为0,遍历到十位会加1的
3.如果是99或999这种情况,则上述遍历不会返回结果
直接返回使用展开运算符将1放至第一位

/**
 * @param {number[]} digits
 * @return {number[]}
 */
var plusOne = function (digits) {
    // 从右往左遍历digits数组
    for (let i = digits.length - 1; i >= 0; i--) {
        // 如果元素不是9,首先是最右边的个位
        if (digits[i] !== 9) {
            // 加1
            digits[i]++
            // 返回数组
            return digits
        // 元素是9,即个位是9
        }else{
            // 仅需将个位置为0,遍历到十位会加1的
            digits[i] = 0
        }
    }
    // 如果是99或999这种情况,则上述遍历不会返回结果
    // 直接使用展开运算符将1放至第一位
    return [1, ...digits]
};

070.爬楼梯

https://leetcode.cn/problems/climbing-stairs/description/

1.创建记忆化数组memo,定义memo[1]和memo[2]
2.遍历n,memo[i] = memo[i - 2] + memo[i - 1]
3.返回memo[n]

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function (n) {
    // 创建记忆化数组memo
    const memo = []
    // 1楼只有1种方法,1
    memo[1] = 1
    // 2楼有2种方法,11,2
    memo[2] = 2
    // 3楼有3种方法,111,12,21
    // 遍历数组n
    for (let i = 3; i <= n; i++) {
        // 到达i的方法数是memo[i-2]和memo[i-1]的和
        memo[i] = memo[i - 2] + memo[i - 1]
    }
    // /返回结果
    return memo[n]
};

073.矩阵置零

https://leetcode.cn/problems/set-matrix-zeroes/description/

1.创建第一列、第一行是否有0标志,默认为false
2.检查第一列是否有0,若有标志设为true;行同理
3.使用第一行和第一列,来标记其余行列是否含有0
遍历matrix数组,从1开始
如果某一个元素是0,将其对应的第一行、第一列,设为0
4.利用第一行、第一列的标0情况,将matrix中的数字标0
遍历matrix数组,从1开始
如果第一行和第一列有标0,将matrix中对应行和列的元素标0
5.处理第一行、第一列
如果第一列是否有0标志为true,将第一列全设为0;行同理
6.返回数组matrix

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var setZeroes = function (matrix) {
    // 设置第一行、第一列标志
    let firstColHasZero = false
    let firstRowHasZero = false
    // 检查第一列是否有0
    for (let i = 0; i < matrix.length; i++) {
        // 如果有0,将第一列标志设为true
        if (matrix[i][0] === 0) {
            firstColHasZero = true
            break
        }
    }
    // 检查第一行是否有0
    for (let i = 0; i < matrix[0].length; i++) {
        // // 如果有0,将第一行标志设为true
        if (matrix[0][i] === 0) {
            firstRowHasZero = true
            break
        }
    }
    // 使用第一行和第一列,来标记其余行列是否含有0
    // 遍历matrix数组,从1开始
    for (let row = 1; row < matrix.length; row++) {
        for (let col = 1; col < matrix[0].length; col++) {
            // 如果某一个元素是0
            if (matrix[row][col] === 0) {
                // 将其对应的第一行和第一列,设为0
                matrix[row][0] = 0
                matrix[0][col] = 0
            }
        }
    }
    // 利用第一行和第一列标0情况,将matrix中的数字标0
    // 遍历matrix数组,从1开始
    for (let row = 1; row < matrix.length; row++) {
        for (let col = 1; col < matrix[0].length; col++) {
            // 如果第一行和第一列有标0,
            if (matrix[row][0] === 0 || matrix[0][col] === 0) {
                // 将matrix中对应行和列标0
                matrix[row][col] = 0
            }
        }
    }
    // 处理第一行和第一列
    // 如果firstColHasZero为true,将第一列全设为0
    if (firstColHasZero) {
        for (let i = 0; i < matrix.length; i++) {
            matrix[i][0] = 0
        }
    }
    // 如果firstRowHasZero为true,将第一行全设为0
    if (firstRowHasZero) {
        for (let i = 0; i < matrix[0].length; i++) {
            matrix[0][i] = 0
        }
    }
    // 返回数组matrix
    return matrix
};

078.子集

https://leetcode.cn/problems/subsets/description/

1.创建结果空数组result
2.定义回溯函数backtrack,start是nums数组的开始查找的索引,curr是待处理的子集数组
把curr数组值传递push([…curr])进result
遍历nums数组,从start开始
把nums[i]push进curr
递归调用(i + 1,curr)
把curr数组pop出最后一个元素
3.backtrack(0, []),让回溯跑起来
4.返回result数组

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function (nums) {
    // 定义结果数组
    const result = []
    // 定义回溯函数,start是nums数组的开始查找的索引,curr是待处理的子集数组
    function backtrack(start, curr) {
        // 将curr数组值传递给result数组
        result.push([...curr])
        // 遍历nums数组,从start开始
        for (let i = start; i < nums.length; i++) {
            // 把nums[i]加入curr数组
            curr.push(nums[i])
            // 递归调用
            backtrack(i + 1, curr)
            // 把curr数组的最后一个元素移除
            curr.pop()
        }
    }
    // 让回溯跑起来,0,[]
    backtrack(0, [])
    // 返回结果数组
    return result
};

090.子集Ⅱ

https://leetcode.cn/problems/subsets-ii/description/

1.创建结果空数组result
2.定义回溯函数backtrack,start是nums数组的开始查找的索引,curr是待处理的子集数组
把curr数组值传递push([…curr])进result
遍历nums数组,从start开始
判断i > start数组中的数是否与上一个相同,相同就continue跳过(i > start确保的是12和122这种情况,不误删122)
把nums[i]push进curr
递归调用(i + 1,curr)
把curr数组pop出最后一个元素
3.backtrack(0, []),让回溯跑起来
4.返回result数组

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsetsWithDup = function (nums) {
    // 定义结果数组
    const result = []
    // 对nums数组升序排序
    nums.sort((a, b) => {
        return a - b
    })
    // 定义回溯函数,start是开始索引,curr是待处理的数组
    function backtrack(start, curr) {
        // 将curr数组值传递给result数组
        result.push([...curr])
        // 遍历nums数组,从start开始
        for (let i = start; i < nums.length; i++) {
            // 判断i > start且数组中的数是否与上一个相同,相同就跳过
            // i>start确保的是12和122这种情况,不误删122
            if (i > start && nums[i] === nums[i - 1]) {
                continue
            }
            // 把nums[i]加入curr数组
            curr.push(nums[i])
            // 递归调用
            backtrack(i + 1, curr)
            // 把curr数组的最后一个元素移除
            curr.pop()
        }
    }
    // 让回溯跑起来,0,[]
    backtrack(0, [])
    // 返回结果数组
    return result
};

083.删除排序链表中的重复元素

https://leetcode.cn/problems/remove-duplicates-from-sorted-list/description/

1.创建curr遍历指针等于head
2.只要curr不为空,且curr的下一位不为空(即只剩最后一位情况)
如果curr的值等于下一位curr的值,删掉下一位节点
否则,指针正常遍历
3.返回head指针

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var deleteDuplicates = function (head) {
    // 定义遍历指针curr
    let curr = head
    // 只要curr不为空,且curr的下一位不为空(即只剩最后一位情况)
    while(curr !== null && curr.next !== null){
        // 如果curr的值等于下一位curr的值
        if(curr.val === curr.next.val){
            // 删掉下一位节点
            curr.next = curr.next.next
        // 如果curr的值不等于下一位curr的值
        }else{
            // 指针正常遍历
            curr = curr.next
        }
    }
    // 返回head指针
    return head
}

206.反转链表

https://leetcode.cn/problems/reverse-linked-list/description/

1.定义后一个指针prev为空,遍历指针curr为head,下一个指针next为head
2.只要curr指针不为空,(next指针是为了占住下一位)
n cn p c
解构赋值curr.next -> prev, prev -> curr, curr -> curr.next
3.返回prev指针

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    // 定义后一个指针prev为空
    let prev = null
    // 定义遍历指针curr为head
    let curr = head
    // 定义下一个指针next为head
    let next = head

    // 只要curr指针不为空
    while(curr !== null){
        // next指针是为了占住下一位
        // n cn p c
        next = curr.next
        curr.next = prev
        prev = curr
        curr = next
        // 解构赋值curr.next -> prev, prev -> curr, curr -> curr.next
        // [curr.next,prev,curr] = [prev,curr,curr.next]
    }
    // 返回prev
    return prev
};

092.反转链表Ⅱ

https://leetcode.cn/problems/reverse-linked-list-ii/description/

1.定义后一个指针prev为空,遍历指针curr为head,下一个指针next为head
2.将curr和prev移到left位,遍历从1至<left
prev = curr, curr = curr.next
3.定义prev2curr2占住位置
4.遍历从left至=right,(next指针是为了占住下一位)
n cn p c
解构赋值curr.next -> prev, prev -> curr, curr -> curr.next
5.如果prev2不等于null,prev2指向prev;否则head指向prev
6.curr2指向curr
7.返回head指针

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} left
 * @param {number} right
 * @return {ListNode}
 */
var reverseBetween = function (head, left, right) {
    // 定义后一个指针prev为空
    let prev = null
    // 定义遍历指针curr为head
    let curr = head
    // 定义下一个指针next为head
    let next = head
    // 将curr和prev移到left位
    for (let i = 1; i < left; i++) {
        prev = curr
        curr = curr.next
    }
    // 定义prev2、curr2占住位置
    let prev2 = prev
    let curr2 = curr
    // 从left至right
    for (let i = left; i <= right; i++) {
        // next指针是为了占住下一位
        // n cn p c
        next = curr.next
        curr.next = prev
        prev = curr
        curr = next
        // 解构赋值curr.next -> prev, prev -> curr, curr -> curr.next
        // [curr.next,prev,curr] = [prev,curr,curr.next]
    }
    // 如果left不为1,即prev不为空
    if(prev2 !== null){
        prev2.next = prev
    // prev为空,left为1
    }else{
        head = prev
    }
    // 让curr2指回占位的curr
    curr2.next = curr
    // 返回head
    return head
};

092.反转链表Ⅱ

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/

1.如果数组为空,返回0
2.初始化最低价格为数组第一位;初始化最大利润为0
3.遍历prices数组
如果值比最低价小,更新最低价格
如果产生了新的最大利润(当前值-最低值),更新最大利润
4.返回最大利润

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
    // 如果数组为空,返回0
    if (prices.length === 0) {
        return 0
    }
    // 初始化最低价格为第一位
    let minPrice = prices[0]
    // 初始化最大利润为0
    let maxProfit = 0

    // 遍历prices数组
    for (let i = 0; i < prices.length; i++) {
        // 如果值比最低价小,更新最低价格
        if (prices[i] < minPrice) {
            minPrice = prices[i]
        // 如果产生了新的最大利润
        } else if (prices[i] - minPrice > maxProfit) {
            maxProfit = prices[i] - minPrice
        }
    }
    // 返回maxprofit
    return maxProfit
};

  • 21
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误信息意味着你正在尝试运行一个叫做“leetcode.toggleleetcodecn”的命令,但是系统找不到这个命令。 这可能是因为你使用的软件或工具不支持这个命令,或者这个命令在你当前的上下文不可用。你可以检查一下你的命令拼写是否正确,或者查看相关的文档和说明来了解如何正确地使用这个命令。 ### 回答2: 当我们在使用LeetCode插件时,可能会遇到错误提示“command 'leetcode.toggleleetcodecn' not found”。这个问出现的原因是插件没有正确安装或者没有激活。下面是解决这个问的几个步骤: 1. 确认插件是否安装成功 首先,我们需要确认LeetCode插件是否已经成功安装。可以通过在VS Code的侧边栏找到“Extensions”图标,然后在搜索框输入“LeetCode”来查找插件是否存在。如果插件存在,那么就说明安装成功。 2. 确认插件是否已经激活 在安装插件之后,我们还需要激活LeetCode插件才能使用它提供的功能。可以在VS Code的侧边栏找到“Extensions”图标,然后点击“Installed”选项卡,在LeetCode插件下方看到是否显示“Activate”按钮,如果是,则需要点击该按钮进行激活。 3. 检查配置项是否正确设置 在安装插件并激活之后,LeetCode插件的配置项需要正确设置才能顺利使用。可以在VS Code的右下角找到“Settings”按钮,然后搜索“LeetCode”来找到插件的配置项。在配置页面可以看到“Language Switch”选项,此处需要确保开启了文支持。 如果以上三个步骤都已经确认完成,但还是遇到了“command 'leetcode.toggleleetcodecn' not found”这个错误,则可以尝试卸载并重新安装插件,或者尝试咨询LeetCode官方支持团队。 ### 回答3: 这个错误提示是因为在使用LeetCode的插件时,该插件没有被正确加载或安装。在使用该插件之前,需要确保已经按照LeetCode插件的安装步骤正确地安装和配置了插件。 为了解决该问,可以采取以下步骤: 1. 检查是否已经安装了VS Code和LeetCode插件。如果没有安装,需要按照官方文档的指导进行安装。 2. 确认已经登录了LeetCode账号。在登录成功之后,需要在LeetCode插件的设置填写正确的账号信息。 3. 检查是否在VS Code的用户设置配置了相关的设置项。在VS Code的用户设置,需要添加以下配置项: ```json "leetcode.endpoint": "https://leetcode-cn.com/graphql", "leetcode.defaultLanguage": "javascript", "leetcode.workspaceFolder": "${workspaceFolder}/leetcode", "leetcode.skeletonFileExtension": "js" ``` 4. 如果 LeetCode 插件的版本不是最新版本,则需要更新插件。在VS Code,可以通过侧边栏的扩展选项或者运行命令“Extensions: Check for Extension Updates”来升级插件。 5. 如果以上步骤都无效,可以尝试重新安装LeetCode插件,并按照官方文档的指导进行配置和使用。 总之,要解决'leetcode.toggleleetcodecn' not found 错误,需要仔细检查和核对安装、配置、登录等这些步骤,以确保LeetCode插件能够正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值