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

JS算法题,LeetCode

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



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

一、排序算法

01.冒泡排序

思路:每次先排出来一个最大的
平均时间复杂度:O(n^2),空间复杂度O(1)
外层循环:排好一个,即索引j减少
内层循环:i++至j
循环体:相邻两位比较大小并交换

	ArrayList.prototype.bubbleSort = function () {
        // 1.获取数组的长度
        const length = this.array.length
        // 第一次:j = length - 1,比较到倒数第一个位置
        // 第二次:j = length - 2,比较到倒数第二个位置
        for (let j = length - 1; j > 0; j--) {
            // j是外层循环的标志,j后面的都已经有序了
            for (let i = 0; i < j; i++) {
                // 升序
                if (this.array[i] > this.array[i + 1]) {
                    [this.array[i], this.array[i + 1]] = [this.array[i + 1], this.array[i]]
                }
            }
        }
    }

02.选择排序

思路:设置min标志,从后面选出最小的,和第min交换位置
平均时间复杂度:O(n^2),空间复杂度O(1)
外层循环:正常遍历j
内层循环:min+1开始
循环体:min>i,min=i

	ArrayList.prototype.selectionSort = function () {
        // 1.获取数组的长度
        const length = this.array.length
        // 2.外层循环:从0位置开始取数据,直到length-2的位置
        for (let j = 0; j < length - 1; j++) {
            // 内循环层:从i+1位置开始,和后面的数据进行比较,直至length-1
            // min用于记录最小的位置
            let min = j
            for (let i = min + 1; i < length; i++) {
                if (this.array[min] > this.array[i]) {
                    min = i
                }
            }
            // 交换min位置的数据和j位置的数据
            [this.array[min], this.array[j]] = [this.array[j], this.array[min]]
        }
    }

03.插入排序

思路:局部有序,前面挨个交换位置
平均时间复杂度:O(n^2),空间复杂度O(1)
外层循环:i从1开始,第一个默认有序
内层循环:设置temp,j=i是局部有序的零界点
循环体:只要j-1>temp,挪动j和j-1,将temp插入到该位置

	ArrayList.prototype.insertSort = function () {
        // 1.获取数组的长度
        let length = this.array.length
        // 2.外层循环:从第1个位置开始获取数据,像前面局部有序进行插入
        for (let i = 1; i < length; i++) {
            // 3.内层循环:获取i位置的元素,和前面的数据依次进行比较
            // i和j是局部有序的临界点
            let temp = this.array[i]
            let j = i
            // 前面局部有序的值>temp,则进行交换,再j--向前挪一位
            while (this.array[j - 1] > temp && j > 0) {
                this.array[j] = this.array[j - 1]
                j--
            }
            // 4.将j位置的数据,放置temp即可
            this.array[j] = temp
        }
    }

04.希尔排序

思路:隔个gap,插入排序,然后缩小gap差距
平均时间复杂度:O(n^(1.3-2)),空间复杂度O(1)
最外层循环:gap>=1,gap向下取整除2
外层循环:i从gap开始,第一个默认有序
内层循环:设置temp,j=i是局部有序的零界点
循环体:只要j-gap>temp,挪动j和j-gap,将temp插入到该位置

	ArrayList.prototype.shellSort = function () {
        // 1.获取数组的长度
        let length = this.array.length
        // 2. 初始化增量gap
        let gap = Math.floor(length / 2)
        // 3. while循环,gap不断减小
        while (gap >= 1) {
            // 4. 以gap作为间隔,进行分组,对分组进行插入排序
            // 从第gap个位置开始获取数据,像前面的第一个局部有序进行插入
            for (let i = gap; i < length; i++) {
                let temp = this.array[i]
                let j = i
                while (j > gap - 1 && this.array[j - gap] > temp) {
                    this.array[j] = this.array[j - gap]
                    j -= gap
                }
                // 5. 将j位置的元素赋值temp
                this.array[j] = temp
            }
            gap = Math.floor(gap / 2)
        }
    }

05.快速排序

思路:递归,双指针。在冒泡排序基础上使用分治思想
只要i<j, j i i j
右边比基数大,j–;比基数小则交换
左边比基数小,i++;比基数大则交换
将pivot放到正确的位置(一趟找到该值所在的正确位置),再分治两侧递归

	function quickSort(arr, left = 0, right = arr.length - 1) {
    // 递归条件,left < right
    if (left < right) {
        // 基准值
        let pivot = arr[left];
        // 左右指针
        let i = left;
        let j = right;
        while (i < j) {
            // 右边比基数大,j--
            while (arr[j] > pivot && i < j) {
                j--;
            }
            // 遇到比基数小,交换
            arr[i] = arr[j];
            // 左边比基数小,i++
            while (arr[i] < pivot && i < j) {
                i++;
            }
            // 遇到比基数大,交换
            arr[j] = arr[i];
        }
        //此时i与j位置一致,将pivot放在此位置即可
        arr[i] = pivot;
        // 对基数左边递归
        quickSort(arr, left, i - 1);
        // 对基数右边递归
        quickSort(arr, i + 1, right);
    // 递归终止条件,left >= right
    } else {
        return;
    }
    // 返回数组
    return arr
}

二、JS手写题

// 1.手写Object.create
// 返回一个obj的实例,即实例的proto指向obj的prototype
function create(obj) {
    function F() { }
    F.prototype = obj
    return new F()
}

// 2.手写instanceof方法
// 使用方法:[] instanceof Array
// left是实例,right是构造函数类
function myInstanceof(left, right) {
    let proto = Object.getPrototypeOf(left)
    let prototype = right.prototype
    while (true) {
        if (proto === null) return false
        if (proto === prototype) return true
        // 注意此处不能let重复声明
        proto = Object.getPrototypeOf(proto)
    }
}
// 测试用例
const arr2 = [1]
console.log(myInstanceof(arr2, Array))

// 3.手写new
function _new() {
    // 创建空对象;this指向obj;执行构造函数;return
    let obj = {}
    // 利用数组shift方法,将arguments的第一个参数,构造函数提出来
    let constructor = Array.prototype.shift.call(arguments)
    obj = Object.create(constructor.prototype)
    // 剩余arguments是数组,使用apply方法
    let result = constructor.apply(obj, arguments)
    // result是构造函数返回的,若是对象,则直接result返回
    return (result !== null && (typeof result === 'object')) ? result : obj
}
// 测试用例
function Person(name, age) {
    this.name = name
    this.age = age
    return {
        name: '张三',
        age: 18
    }
}
console.log(_new(Person, 'Hugh', 24))

// 4.手写Promise

// 5.手写promise.then

// 6.手写PromiseAll
function promiseAll(promises) {
    return new Promise((resolve, reject) => {
        if (!Array.isArray(promises)) {
            throw new Error('参数类型应为数组')
        }
        let result = []
        let nums = promises.length
        let count = 0
        for (let i = 0; i < nums; i++) {
            Promise.resolve(promises[i]).then(
                value => {
                    count++
                    result[i] = value
                    if (count == nums) {
                        return resolve(result)
                    }
                }, error => {
                    reject(error)
                }
            )
        }
    })
}

// 7.手写promise.race


// 8.手写防抖
function debounce(fn, wait) {
    let timer = null

    return function () {
        let context = this
        let args = arguments

        if (timer) {
            clearTimeout(timer)
            timer = null
        }
        timer = setTimeout(() => {
            fn.apply(context, args)
        }, wait)
    }
}

// 9.手写节流
function throttle(fn, delay) {
    let currTime = Date.now()

    return function () {
        let context = this
        let args = arguments
        let nowTime = Date.now()

        if (nowTime - currTime > delay) {
            fn.apply(context, args)
            currTime = Date.now()
        }
    }
}

// 10.手写类型判断

// 11.手写call
// 使用方法:fn.call(obj,25,'男')
Function.prototype.myCall = function (context) {
    // context若为空则挂载至window
    context = context || window
    // 获取参数:设置args为除了第一个参数外的所有参数
    let args = [...arguments].splice(1);
    const fn = Symbol('key')
    context[fn] = this
    const result = context[fn](...args)
    delete context[fn]
    return result
}
// 测试用例
const obj11 = {
    name: 'OBJECT11'
}
function fn11(age, sex) {
    console.log(this.name, age, sex)
}
fn11.myCall(obj11, 25, '男')

// 12.手写apply
// 使用方法:fn.apply(obj,[25,'男'])
Function.prototype.myApply = function (context) {
    const context = context || window
    const fn = Symbol('key')
    context[fn] = this
    let result
    // 判断是否有第二个参数
    if (arguments[1]) {
        context[fn](...arguments[1])
    } else {
        context[fn]()
    }
    delete context[fn]
    return result
}
// 测试用例
const obj12 = {
    name: 'OBJECT12'
}
function fn12(age, sex) {
    console.log(this.name, age, sex)
}
fn12.myApply(obj12, [25, '男'])

// 13.手写bind
// 使用方法:fn.bind(obj,25,'男')()
Function.prototype.myBind = function (context) {
    let args = [...arguments].splice(1)
    return function Fn() {
        return this.apply(this instanceof Fn ? this : context, args.concat(...arguments))
    }
}
// 测试用例
const obj13 = {
    name: 'OBJECT13'
}
function fn13(age, sex) {
    console.log(this.name, age, sex)
}
fn13.myBind(obj13, [25, '男'])()
// 14.柯里化函数

// 15.手写ajax
const _URL = "/server"
let xhr = new XMLHttpRequest()
xhr.open('GET', _URL, true)
xhr.onreadystatechange = function () {
    if (this.readyState !== 4) return
    if (this.status === 200) {
        handle(this.response)
    } else {
        console.error(this.statusText)
    }
}
xhr.onerror = function () {
    console.error(this.statusText)
}
xhr.setRequestHeader("Accept", "application/json")
xhr.send()


// 16.Promise封装ajax
function getJSON(url) {
    let promise = new Promise(function (resolve, reject) {
        let xhr = new XMLHttpRequest()
        xhr.open('GET', _URL, true)
        xhr.onreadystatechange = function () {
            if (this.readyState !== 4) return
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.onerror = function () {
            reject(new Error(this.statusText))
        }
        xhr.setRequestHeader("Accept", "application/json")
        xhr.send()
    })
    return promise
}


// 17.浅拷贝
Object.assign(target, source_1, source_2)


// 18. 深拷贝
JSON.parse(JSON.stringify(obj))
// 递归实现
function deepClone(obj) {
    // 判空或不是对象
    if (obj == null || typeof obj !== "object") { return }
    // newObj isArray ?[]:{}
    let newObj = Array.isArray(obj) ? [] : {}
    // 遍历对象
    for (let key in obj) {
        // 判断key是否是object自身上的,而不是其原型链上
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === "object" ? deepClone(obj[key]) : obj[key]
        }
    }
    return newObj
}
// 测试用例
const person = {
    name: 'hugh',
    age: 25,
    hobby: {
        hName: '羽毛球'
    }
}
console.log(deepClone(person))

// 12.实现sleep函数
function sleep(t) {
    return new Promise(resolve => setTimeout(resolve, t))
}
// 测试用例
console.log('sleep函数')
sleep(1000).then(() => {
    console.log('1秒后执行')
})
// 20.实现Object.assign()







// 21.实现日期格式化函数

// 22.交换a、b的值,不用临时变量
a = a + b
b = a - b
a = a - b

// 23.打乱数组
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.sort(() => Math.random() - 0.5)
console.log(arr)

// 24.数组求和
// reduce求和
arr.reduce((prev, item) => prev += item, 0)
// 递归求和
function add(arr) {
    if (arr.length === 1) return arr[0]
    return arr[0] + add(arr.slice(1))
}

// 25.手写扁平化数组
// ES6中flat
arr.flat(Infinity)
// split和toString
arr.toString.split(",")
// 递归
function flatten(arr) {
    let result = []
    for (i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            result = result.concat(flatten(arr[i]))
        } else {
            result.push(arr[i])
        }
    }
}

// 26.数组去重
Array.from(new Set(arr))

// 27.





三、LeetCode

000.ACM模式输入

多行输⼊,每行两个整数

// 引⼊readline模块来读取标准输⼊
const readline = require('readline');
// 创建readline接⼝
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
// 处理输⼊和输出
function processInput() {
    rl.on('line', (input) => {
        // 将输⼊按空格分割成a和b的数组
        const [a, b] = input.split(' ').map(Number);
        // 计算a和b的和并输出
        const sum = a + b;
        console.log(sum);
    });
}
// 开始处理输⼊
processInput();

001.两数之和

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

变量:map,complement
方法:map里是否有complement
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/

变量:dummy,curry,carry
方法:sum->curr.next->carry->curr
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/

变量:set,i,j,maxLength
方法:set是否有s[i]
1.创建set,定义双遍历指针 i 和 j 都为0
2.定义无重复字符串最大长度maxLength为0,遍历字符串
3.如果set还有s[i]
while循环确保set不存在s[i]*
4.*如果
set里没有s[i],即没有重复过的字符
s[i]添加进set**,并更新maxLength的值,取maxLength和set.size的max值
删除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])){
            // 这里要用while,确保set里不存在s[j]
            while(set.has(s[i])){
                // 删除s[j],即第一次出现的重复值
                set.delete(s[j])
                // 将j指向下一个值
                j++
            }
            // 再将s[i]加入set里
            set.add(s[i])
        }else{
            // 如果set里没有s[i],即没有重复过的字符
            // 添加进set
            set.add(s[i])
            // 更新无重复字符的最长子串的值
            maxLength = Math.max(maxLength, set.size)
        }
    }
    // 返回无重复字符的最长子串的值
    return maxLength
};

005.最长回文子串

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

变量:start,maxLength
方法:中心扩展算法expandAroundCenter
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/

变量:i,start,end
方法:nums升序,确保数组不重复
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/

变量:dummy,start,end
方法:双指针滑动窗口,遍历n控制end位置
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/

变量:map,stack
方法:map存括号,stack模拟栈,左括号push,右括号pop
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/

变量:dummy,curr
1.创建空链表dummy,curry指向dummy
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) {
    // 创建一个空结点dummy作为新链表
    let dummy = new ListNode()
    // 让curr指向dummy
    let curr = dummy

    // 只要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/

变量:dummy,curr
1.创建空节点dummy指向head,创建遍历指针curr指向dummy
2.只要curr后还有2个节点不为空
3.定义n1和n2,分别是curr的下一个节点和下下个节点
4.curr.next; n1.next ; n2.next
5.curr指向n1,此时curr下一个节点为n2,应跳过n2节点
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,此时curr下一个节点为n2,应跳过n2节点
        curr = n1
    }
    // 返回交换后的链表头节点
    return dummy.next
};

049.字母异位词分组

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

变量:map,characters,ascii,key
方法:创建key,map有就追加,没有就添加
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 === 0){
        // 如果为空,返回空数组
        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/

变量:memo,max
方法:for循环从1开始,memo[i - 1] + nums[i], nums[i]
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/

变量:上下左右边界,direction
方法:只要不越界,右下左上,i是右左右左
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/

变量:maxJump
方法:Greedy贪心算法,length-2至0,i+nums[i]>=maxJump
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
};

056.合并区间

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

变量:curr,result,interval
方法:长度判断<2,数组升序,遍历数组curr1[1]和interval[0],判断curr的length为空
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/

遍历:memo二维数组
方法:第1行和第1列都为1,m为row,n为col,遍历二维数组,memo[row][col] = memo[row - 1][col] + memo[row][col - 1]
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数组
    // m是行,n是列;按照行再创建数组
    for (let i = 0; i < m; i++) {
        memo.push([])
    }
    // 第一列和第一行的路径只有1条
    // 填充第一列为1
    for (let row = 0; row < m; row++) {
        memo[row][0] = 1
    }
    // 填充第一行为1
    for (let col = 0; col < n; col++) {
        memo[0][col] = 1
    }
    // 遍历memo二维数组
    for (let row = 1; row < m; row++) {
        for (let col = 1; col < n; col++) {
            // 新格子的不同路径数 = 左边格子和上边格子路径数之和
            memo[row][col] = memo[row - 1][col] + memo[row][col - 1]
        }
    }
    // 返回结果,索引要-1
    return memo[m-1][n-1]
};


066.加一

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

方法:右往左遍历,是不是9,进位处理[1,…digits]
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/

变量:memo数组
方法:DP,1 2 3<=n
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/

变量:m,n,row,col
方法:遍历二维数组,通过元素为0设置row和col;通过row和col状态设置零
1.创建m、n,m是row,n是col
2.Array().fill(false)填充row和col
3.遍历二维数组,如果某一个元素是0,将其对应的row、col,设为true
4.遍历二维数组,如果row或col是true,将其对应的元素置为0

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var setZeroes = function(matrix) {
    // m是行,n是列
    const m = matrix.length, n = matrix[0].length;
    // 两个标记数组row和col,填充false
    const row = new Array(m).fill(false);
    const col = new Array(n).fill(false);
    // 遍历二维数组,将0所在行和列的标记数组置为true
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (matrix[i][j] === 0) {
                row[i] = col[j] = true;
            }
        }
    }
    // 遍历二维数组,通过标记数组row和col的状态来置零
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (row[i] || col[j]) {
                matrix[i][j] = 0;
            }
        }
    }
};

078.子集(元素互不相同)

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

变量:result
方法:回溯 rpc cpi bic cp
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/

变量:result
方法:升序,回溯,rpc cpi bic cp,i > start && nums[i] === nums[i - 1] 跳过
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/

变量:curr
方法:不为空,比较值,跳过
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/

变量:n p c
方法:n cn p c
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/

变量:n p c
方法:p和c移位置,p2,c2占位置,n cn p c,p2指向p,c2指向c
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
};

121.买卖股票的最佳时机(只能交易一次)

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

变量:minPrice,maxProfit
方法:数组判空,最低价小更新,最大利润大更新
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
};

122.买卖股票的最佳时机Ⅱ(可以交易多次)

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

变量:profit
方法:贪心算法,数组判空,今天小于明天即加上利润
1.如果数组为空,返回0
2.初始化利润为0
3.遍历prices数组,i<length-1,因为要和第二天比较
如果今天比明天小,更新利润,即加上两天的差
4.返回利润

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
    // 数组判空
    if (prices.length === 0) {
        return 0
    }
    // 初始化利润为0
    let profit = 0
    // 遍历price数组,i < prices.length - 1,因为会和第二天比较
    for (let i = 0; i < prices.length - 1; i++) {
        // 如果第一天的值<第二天的值,即有利润
        if (prices[i] < prices[i + 1]) {
            // 更新利润
            profit += prices[i + 1] - prices[i]
        }
    }
    // 返回利润
    return profit
};

  • 30
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值