1. 程式人生 > >【Leetcode 做題學演算法週刊】第三期

【Leetcode 做題學演算法週刊】第三期

首發於微信公眾號《前端成長記》,寫於 2019.11.13

背景

本文記錄刷題過程中的整個思考過程,以供參考。主要內容涵蓋:

  • 題目分析設想
  • 編寫程式碼驗證
  • 查閱他人解法
  • 思考總結

目錄

  • 35.搜尋插入位置
  • 38.報數
  • 53.最大子序和
  • 58.最後一個單詞的長度
  • 66.加一

Easy

35.搜尋插入位置

題目地址

題目描述

給定一個排序陣列和一個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。

你可以假設陣列中無重複元素。

示例:

輸入: [1,3,5,6], 5
輸出: 2

輸入: [1,3,5,6], 2
輸出: 1

輸入: [1,3,5,6], 7
輸出: 4

輸入: [1,3,5,6], 0
輸出: 0

題目分析設想

這道題目有點明顯,題幹說明了是排序陣列,重點是排序陣列,所以很明顯的第一反應會使用二分法來解題。同時可以注意一下,陣列中無重複元素。所以這道題我就按兩個方案來作答:

  • 暴力法,直接遍歷
  • 二分法,可以理解成不斷折半排除不可能

編寫程式碼驗證

Ⅰ.暴力法

程式碼:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    if (nums.length === 0 || nums[0] > target) return 0;
    if(nums[nums.length - 1] < target) return nums.length;

    for(let i = 0; i < nums.length; i++) {
        if(nums[i] >= target) return i
    }
};

結果:

  • 62/62 cases passed (60 ms)
  • Your runtime beats 92.48 % of javascript submissions
  • Your memory usage beats 63.22 % of javascript submissions (33.8 MB)
  • 時間複雜度 O(n)

Ⅱ.二分法

程式碼:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    if (nums.length === 0 || nums[0] > target) return 0;
    if(nums[nums.length - 1] < target) return nums.length;

    let left = 0; // 起點
    let right = nums.length - 1; // 終點
    while(left < right) {
         // 零填充右位移,使用位運算避免溢位,大部分情況下等於 (left + right / 2)
        let i = parseInt((left + right) >>> 1) // 這裡選擇取左
        if (nums[i] < target) { // 中位數小於目標值
            left = i + 1 // 排除中位數左側
        } else {
            right = i // 排除中位數右側
        }
    }
    return left
};

結果:

  • 62/62 cases passed (52 ms)
  • Your runtime beats 99.31 % of javascript submissions
  • Your memory usage beats 61.31 % of javascript submissions (33.8 MB)
  • 時間複雜度 O(log2(n))

查閱他人解法

基本上這道題就是針對二分法進行考察的,所以沒有看到其他特別的解法。

思考總結

看見排序陣列,查詢下標,那麼就可以果斷選擇二分法啦。

38.報數

題目地址

題目描述

報數序列是一個整數序列,按照其中的整數的順序進行報數,得到下一個數。其前五項如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221

1 被讀作 "one 1" ("一個一"),即 11

11 被讀作 "two 1s" ("兩個一"),即 21

21 被讀作 "one 2", "one 1""一個二" , "一個一") , 即 1211

給定一個正整數 n(1 ≤ n ≤ 30),輸出報數序列的第 n 項。

注意:整數順序將表示為一個字串。

示例:

輸入: 1
輸出: "1"

輸入: 4
輸出: "1211"

題目分析設想

這道題目有點繞,其實我們只看右側項就可以,每次都是讀上一次項。報數的規則實際上就是相同連續數字合併後進行每位的報數。最簡單的想法是直接使用正則替換就可以了。當然也可以從遞迴和遍歷的方式來作答,我們分別來看看。

  • 正則法,替換相同連續數字為 長度 + 數字本身
  • 遞迴法,不斷轉換成 n-1 求解
  • 遍歷法,不斷轉換成 n+1 求解

編寫程式碼驗證

Ⅰ.正則法

程式碼:

/**
 * @param {number} n
 * @return {string}
 */
var countAndSay = function(n) {
    let str = '1'
    for(let i = 1; i < n; i++) {
        // 匹配項長度+第一位即為讀數
        str = str.replace(/(\d)\1*/g, (match) => (`${match.length}${match.charAt(0)}`))
    }
    return str
};

結果:

  • 18/18 cases passed (56 ms)
  • Your runtime beats 98.81 % of javascript submissions
  • Your memory usage beats 32.53 % of javascript submissions (35.6 MB)
  • 時間複雜度 O(n)

Ⅱ.遞迴法

程式碼:

/**
 * @param {number} n
 * @return {string}
 */
var countAndSay = function(n) {
    if (n === 1) return '1'
    debugger
    let str = countAndSay(n - 1)
    let item = str.charAt(0)

    let count = 0 // 計數器
    let res = ''
    for(let i = 0; i < str.length; i++) {
        if(str.charAt(i) === item) {
            count++
        } else {
            res += `${count}${item}`
            item = str.charAt(i)
            count = 1
        }

        if (i === str.length - 1) { // 最後一位,需要取數
            res += `${count}${item}`
        }
    }
    return res
};

結果:

  • 18/18 cases passed (64 ms)
  • Your runtime beats 92.23 % of javascript submissions
  • Your memory usage beats 28.23 % of javascript submissions (35.7 MB)
  • 時間複雜度 O(n^2)

Ⅲ.遍歷法

程式碼:

/**
 * @param {number} n
 * @return {string}
 */
var countAndSay = function(n) {
    let str = '1'
    for(let i = 1; i < n; i++) {
        str = countEach(str)
    }
    function countEach(str) {
        let count = 0
        let res = ''
        for(let i = 0; i < str.length; i++) {
            if(i === 0 || str.charAt(i) === str.charAt(i - 1)) {
                count++
            } else {
                res += `${count}${str.charAt(i - 1)}`
                count = 1
            }
            if (i === str.length - 1) {
                res += `${count}${str.charAt(i)}`
            }
        }

        return res
    }

    return str
};

結果:

  • 18/18 cases passed (60 ms)
  • Your runtime beats 96.98 % of javascript submissions
  • Your memory usage beats 41.69 % of javascript submissions (35.5 MB)
  • 時間複雜度 O(n^2)

查閱他人解法

這裡看到一個開懷一笑的解法,直接字典法,缺點很明顯,但是當前情況下確實是最快的。

Ⅰ.正則法

程式碼:

/**
 * @param {number} n
 * @return {string}
 */
var countAndSay = function(n) {
    const map = {
        1:"1",
        2:"11",
        3:"21",
        4:"1211",
        5:"111221",
        6:"312211",
        7:"13112221",
        8:"1113213211",
        9:"31131211131221",
        10:"13211311123113112211",
        11:"11131221133112132113212221",
        12:"3113112221232112111312211312113211",
        13:"1321132132111213122112311311222113111221131221",
        14:"11131221131211131231121113112221121321132132211331222113112211",
        15:"311311222113111231131112132112311321322112111312211312111322212311322113212221",
        16:"132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211",
        17:"11131221131211132221232112111312212321123113112221121113122113111231133221121321132132211331121321231231121113122113322113111221131221",
        18:"31131122211311123113321112131221123113112211121312211213211321322112311311222113311213212322211211131221131211132221232112111312111213111213211231131122212322211331222113112211",
        19:"1321132132211331121321231231121113112221121321132122311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112311332111213122112311311123112111331121113122112132113213211121332212311322113212221",
        20:"11131221131211132221232112111312111213111213211231132132211211131221131211221321123113213221123113112221131112311332211211131221131211132211121312211231131112311211232221121321132132211331121321231231121113112221121321133112132112312321123113112221121113122113121113123112112322111213211322211312113211",
        21:"311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122211311122122111312211213211312111322211213211321322113311213212322211231131122211311123113223112111311222112132113311213211221121332211211131221131211132221232112111312111213111213211231132132211211131221232112111312211213111213122112132113213221123113112221131112311311121321122112132231121113122113322113111221131221",
        22:"132113213221133112132123123112111311222112132113311213211231232112311311222112111312211311123113322112132113213221133122112231131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112131221123113111231121113311211131221121321131211132221123113112211121312211231131122211211133112111311222112111312211312111322211213211321322113311213211331121113122122211211132213211231131122212322211331222113112211",
        23:"111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122211331121321232221121113122113121113222123112221221321132132211231131122211331121321232221123113112221131112311332111213122112311311123112112322211211131221131211132221232112111312211322111312211213211312111322211231131122111213122112311311221132211221121332211213211321322113311213212312311211131122211213211331121321123123211231131122211211131221131112311332211213211321223112111311222112132113213221123123211231132132211231131122211311123113322112111312211312111322212321121113122123211231131122113221123113221113122112132113213211121332212311322113212221",
        24:"3113112221131112311332111213122112311311123112111331121113122112132113121113222112311311221112131221123113112221121113311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112311332111213213211221113122113121113222112132113213221232112111312111213322112132113213221133112132123123112111311222112132113311213211221121332211231131122211311123113321112131221123113112221132231131122211211131221131112311332211213211321223112111311222112132113212221132221222112112322211211131221131211132221232112111312111213111213211231132132211211131221232112111312211213111213122112132113213221123113112221133112132123222112111312211312112213211231132132211211131221131211132221121311121312211213211312111322211213211321322113311213212322211231131122211311123113321112131221123113112211121312211213211321222113222112132113223113112221121113122113121113123112112322111213211322211312113211",
        25:"132113213221133112132123123112111311222112132113311213211231232112311311222112111312211311123113322112132113212231121113112221121321132132211231232112311321322112311311222113111231133221121113122113121113221112131221123113111231121123222112132113213221133112132123123112111312111312212231131122211311123113322112111312211312111322111213122112311311123112112322211211131221131211132221232112111312111213111213211231132132211211131221232112111312212221121123222112132113213221133112132123123112111311222112132113213221132213211321322112311311222113311213212322211211131221131211221321123113213221121113122113121132211332113221122112133221123113112221131112311332111213122112311311123112111331121113122112132113121113222112311311221112131221123113112221121113311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112212211131221121321131211132221123113112221131112311332211211133112111311222112111312211311123113322112111312211312111322212321121113121112133221121321132132211331121321231231121113112221121321132122311211131122211211131221131211322113322112111312211322132113213221123113112221131112311311121321122112132231121113122113322113111221131221",
        26:"1113122113121113222123211211131211121311121321123113213221121113122123211211131221121311121312211213211321322112311311222113311213212322211211131221131211221321123113213221121113122113121113222112131112131221121321131211132221121321132132211331121321232221123113112221131112311322311211131122211213211331121321122112133221121113122113121113222123211211131211121311121321123113111231131122112213211321322113311213212322211231131122211311123113223112111311222112132113311213211221121332211231131122211311123113321112131221123113111231121113311211131221121321131211132221123113112211121312211231131122113221122112133221121113122113121113222123211211131211121311121321123113213221121113122113121113222113221113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111221132221231221132221222112112322211213211321322113311213212312311211131122211213211331121321123123211231131122211211131221131112311332211213211321223112111311222112132113213221123123211231132132211231131122211311123113322112111312211312111322111213122112311311123112112322211213211321322113312211223113112221121113122113111231133221121321132132211331121321232221123123211231132132211231131122211331121321232221123113112221131112311332111213122112311311123112112322211211131221131211132221232112111312111213111213211231132132211211131221131211221321123113213221123113112221131112211322212322211231131122211322111312211312111322211213211321322113311213211331121113122122211211132213211231131122212322211331222113112211",
        27:"31131122211311123113321112131221123113111231121113311211131221121321131211132221123113112211121312211231131122211211133112111311222112111312211312111322211213211321322123211211131211121332211231131122211311122122111312211213211312111322211231131122211311123113322112111331121113112221121113122113111231133221121113122113121113222123211211131211121332211213211321322113311213211322132112311321322112111312212321121113122122211211232221123113112221131112311332111213122112311311123112111331121113122112132113311213211321222122111312211312111322212321121113121112133221121321132132211331121321132213211231132132211211131221232112111312212221121123222112132113213221133112132123123112111311222112132113311213211231232112311311222112111312211311123113322112132113212231121113112221121321132122211322212221121123222112311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122211311123113322113223113112221131112311332211211131221131211132211121312211231131112311211232221121321132132211331221122311311222112111312211311123113322112132113213221133122211332111213112221133211322112211213322112111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122211331121321232221121113122113121122132112311321322112111312211312111322211213111213122112132113121113222112132113213221133112132123222112311311222113111231132231121113112221121321133112132112211213322112111312211312111322212311222122132113213221123113112221133112132123222112111312211312111322212321121113121112133221121311121312211213211312111322211213211321322123211211131211121332211213211321322113311213212312311211131122211213211331121321122112133221123113112221131112311332111213122112311311123112111331121113122112132113121113222112311311222113111221221113122112132113121113222112132113213221133122211332111213322112132113213221132231131122211311123113322112111312211312111322212321121113122123211231131122113221123113221113122112132113213211121332212311322113212221",
        28:"13211321322113311213212312311211131122211213211331121321123123211231131122211211131221131112311332211213211321223112111311222112132113213221123123211231132132211231131122211311123113322112111312211312111322111213122112311311123112112322211213211321322113312211223113112221121113122113111231133221121321132132211331121321232221123123211231132132211231131122211331121321232221123113112221131112311332111213122112311311123112112322211211131221131211132221232112111312211322111312211213211312111322211231131122111213122112311311221132211221121332211213211321322113311213212312311211131122211213211331121321123123211231131122211211131221232112111312211312113211223113112221131112311332111213122112311311123112112322211211131221131211132221232112111312211322111312211213211312111322211231131122111213122112311311221132211221121332211211131221131211132221232112111312111213111213211231132132211211131221232112111312211213111213122112132113213221123113112221133112132123222112111312211312112213211231132132211211131221131211322113321132211221121332211213211321322113311213212312311211131122211213211331121321123123211231131122211211131221131112311332211213211321322113311213212322211322132113213221133112132123222112311311222113111231132231121113112221121321133112132112211213322112111312211312111322212311222122132113213221123113112221133112132123222112111312211312111322212311322123123112111321322123122113222122211211232221123113112221131112311332111213122112311311123112111331121113122112132113121113222112311311221112131221123113112221121113311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112212211131221121321131211132221123113112221131112311332211211133112111311222112111312211311123113322112111312211312111322212321121113121112133221121321132132211331121321132213211231132132211211131221232112111312212221121123222112311311222113111231133211121321321122111312211312111322211213211321322123211211131211121332211231131122211311123113321112131221123113111231121123222112111331121113112221121113122113111231133221121113122113121113221112131221123113111231121123222112111312211312111322212321121113121112131112132112311321322112111312212321121113122122211211232221121321132132211331121321231231121113112221121321133112132112312321123113112221121113122113111231133221121321132132211331221122311311222112111312211311123113322112111312211312111322212311322123123112112322211211131221131211132221132213211321322113311213212322211231131122211311123113321112131221123113112211121312211213211321222113222112132113223113112221121113122113121113123112112322111213211322211312113211",
        29:"11131221131211132221232112111312111213111213211231132132211211131221232112111312211213111213122112132113213221123113112221133112132123222112111312211312112213211231132132211211131221131211132221121311121312211213211312111322211213211321322113311213212322211231131122211311123113223112111311222112132113311213211221121332211211131221131211132221231122212213211321322112311311222113311213212322211211131221131211132221232112111312111213322112131112131221121321131211132221121321132132212321121113121112133221121321132132211331121321231231121113112221121321133112132112211213322112311311222113111231133211121312211231131122211322311311222112111312211311123113322112132113212231121113112221121321132122211322212221121123222112111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122111213122112311311222113111221131221221321132132211331121321231231121113112221121321133112132112211213322112311311222113111231133211121312211231131122211322311311222112111312211311123113322112132113212231121113112221121321132122211322212221121123222112311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111221132221231221132221222112112322211211131221131211132221232112111312111213111213211231132132211211131221232112111312211213111213122112132113213221123113112221133112132123222112111312211312111322212321121113121112133221132211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211213211321322113311213212312311211131122211213211331121321123123211231131122211211131221131112311332211213211321223112111311222112132113213221123123211231132132211231131122211311123113322112111312211312111322111213122112311311123112112322211213211321322113312211223113112221121113122113111231133221121321132132211331121321232221123123211231132132211231131122211331121321232221123113112221131112311332111213122112311311123112112322211211131221131211132221232112111312211322111312211213211312111322211231131122111213122112311311221132211221121332211213211321322113311213212312311211131211131221223113112221131112311332211211131221131211132211121312211231131112311211232221121321132132211331121321231231121113112221121321133112132112211213322112312321123113213221123113112221133112132123222112311311222113111231132231121113112221121321133112132112211213322112311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311221132211221121332211211131221131211132221232112111312111213111213211231132132211211131221232112111312211213111213122112132113213221123113112221133112132123222112111312211312111322212311222122132113213221123113112221133112132123222112311311222113111231133211121321132211121311121321122112133221123113112221131112311332211322111312211312111322212321121113121112133221121321132132211331121321231231121113112221121321132122311211131122211211131221131211322113322112111312211322132113213221123113112221131112311311121321122112132231121113122113322113111221131221",
        30:"3113112221131112311332111213122112311311123112111331121113122112132113121113222112311311221112131221123113112221121113311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112212211131221121321131211132221123113112221131112311332211211133112111311222112111312211311123113322112111312211312111322212321121113121112133221121321132132211331121321132213211231132132211211131221232112111312212221121123222112311311222113111231133211121321321122111312211312111322211213211321322123211211131211121332211231131122211311123113321112131221123113111231121123222112111331121113112221121113122113111231133221121113122113121113221112131221123113111231121123222112111312211312111322212321121113121112131112132112311321322112111312212321121113122122211211232221121321132132211331121321231231121113112221121321132132211322132113213221123113112221133112132123222112111312211312112213211231132132211211131221131211322113321132211221121332211231131122211311123113321112131221123113111231121113311211131221121321131211132221123113112211121312211231131122211211133112111311222112111312211312111322211213211321223112111311222112132113213221133122211311221122111312211312111322212321121113121112131112132112311321322112111312212321121113122122211211232221121321132132211331121321231231121113112221121321132132211322132113213221123113112221133112132123222112111312211312112213211231132132211211131221131211322113321132211221121332211213211321322113311213212312311211131122211213211331121321123123211231131122211211131221131112311332211213211321223112111311222112132113213221123123211231132132211231131122211311123113322112111312211312111322111213122112311311123112112322211213211321322113312211223113112221121113122113111231133221121321132132211331222113321112131122211332113221122112133221123113112221131112311332111213122112311311123112111331121113122112132113121113222112311311221112131221123113112221121113311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112311332111213122112311311123112112322211322311311222113111231133211121312211231131112311211232221121113122113121113222123211211131221132211131221121321131211132221123113112211121312211231131122113221122112133221121321132132211331121321231231121113121113122122311311222113111231133221121113122113121113221112131221123113111231121123222112132113213221133112132123123112111312211322311211133112111312211213211311123113223112111321322123122113222122211211232221121113122113121113222123211211131211121311121321123113213221121113122123211211131221121311121312211213211321322112311311222113311213212322211211131221131211221321123113213221121113122113121113222112131112131221121321131211132221121321132132211331121321232221123113112221131112311322311211131122211213211331121321122112133221121113122113121113222123112221221321132132211231131122211331121321232221121113122113121113222123211211131211121332211213111213122112132113121113222112132113213221232112111312111213322112132113213221133112132123123112111311222112132113311213211221121332211231131122211311123113321112131221123113112221132231131122211211131221131112311332211213211321223112111311222112132113212221132221222112112322211211131221131211132221232112111312111213111213211231131112311311221122132113213221133112132123222112311311222113111231132231121113112221121321133112132112211213322112111312211312111322212321121113121112131112132112311321322112111312212321121113122122211211232221121311121312211213211312111322211213211321322123211211131211121332211213211321322113311213211322132112311321322112111312212321121113122122211211232221121321132132211331121321231231121113112221121321133112132112312321123113112221121113122113111231133221121321132122311211131122211213211321222113222122211211232221123113112221131112311332111213122112311311123112111331121113122112132113121113222112311311221112131221123113112221121113311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112311332111213213211221113122113121113222112132113213221232112111312111213322112132113213221133112132123123112111312211322311211133112111312212221121123222112132113213221133112132123222113223113112221131112311332111213122112311311123112112322211211131221131211132221232112111312111213111213211231132132211211131221131211221321123113213221123113112221131112211322212322211231131122211322111312211312111322211213211321322113311213211331121113122122211211132213211231131122212322211331222113112211"
    }

    return map[n]
};

結果:

  • 18/18 cases passed (56 ms)
  • Your runtime beats 98.81 % of javascript submissions
  • Your memory usage beats 98.5 % of javascript submissions (33.5 MB)
  • 時間複雜度 O(1)

思考總結

總體而言,這道題用正則去解答十分簡單,考驗的點在正則的匹配這塊;當然遞迴或者遍歷也是常規思路;字典法純屬一樂。推薦使用正則來解答此題。

53.最大子序和

題目地址

題目描述

給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。

示例:

輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。

進階:

如果你已經實現複雜度為 O(n) 的解法,嘗試使用更為精妙的分治法求解。

題目分析設想

這道題首先基本解法肯定是暴力的遍歷求解,直接遍歷找出最大區間。當然這裡我們也可以使用動態規劃來思考問題,列出動態和轉移方程式,等於求解 Max(d[0, i])。另外進階裡面提示分治法,分治法在之前有用過,我們也可以做為一個方向。所以大概有三種:

  • 遍歷求解,直接遍歷算出各區間值
  • 動態規劃問題,求解動態問題,找到每個動態區間的最大值
  • 分治,不斷二分找區間內的最大子序和

注意一下,只要是尋找最大值最小值的,初始值需要定義為理論上的最大最小值。

編寫程式碼驗證

Ⅰ.遍歷求解

程式碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let res = Number.MIN_SAFE_INTEGER
    for(let i = 0; i < nums.length; i++) {
        let sum = 0
        // 分別算出 i 開始的最大子序和
        for(let j = i; j < nums.length; j++) {
            sum += nums[j];
            res = Math.max(res, sum)
        }
    }
    return res
};

結果:

  • 202/202 cases passed (272 ms)
  • Your runtime beats 7.61 % of javascript submissions
  • Your memory usage beats 41.88 % of javascript submissions (35.1 MB)
  • 時間複雜度 O(n^2)

Ⅱ.動態規劃

程式碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let res = dp = nums[0] // 初始值
    for(let i = 1; i < nums.length; i++) {
        dp = Math.max(dp + nums[i], nums[i]) // 動態取得最大值
        res = Math.max(res, dp)
    }
    return res
};

結果:

  • 202/202 cases passed (68 ms)
  • Your runtime beats 90.14 % of javascript submissions
  • Your memory usage beats 45 % of javascript submissions (35.1 MB)
  • 時間複雜度 O(n)

Ⅲ.分治

程式碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    // 不斷分治
    function countByDichotomy (start, end) {
        // 儲存左側結果,右側結果,兩者更大值,以及兩者相加的值
        // 解釋一下:最大子序列在左右兩區間內要麼過界要麼不過界。
        // 如果不過界,則最大值為 Max(left, right)
        // 如果過界,則最大為左區間到中間的最大值加中間到右區間的最大值
        if (end === start) { // 陣列就一項
            return {
                lmax: nums[start], // 左半區間包含其右端點的最大子序和
                rmax: nums[start], // 右半區間包含其左端點的最大子序和
                sum: nums[start], // 總和
                result: nums[start] // 區域內部的最大子序和
            }
        } else {
            const mid = (start + end) >>> 1 // 這個取中位數寫法之前解釋過,避免溢位
            const left = countByDichotomy(start, mid) // 左區間中計算結果
            const right = countByDichotomy(mid + 1, end) // 右區間中計算結果
            return {
                lmax: Math.max(left.lmax, left.sum + right.lmax),
                rmax: Math.max(right.rmax, left.rmax + right.sum),
                sum: left.sum + right.sum,
                result: Math.max(left.rmax + right.lmax, Math.max(left.result, right.result))
            }
        }
    }
    return countByDichotomy(0, nums.length - 1).result;
};

結果:

  • 202/202 cases passed (60 ms)
  • Your runtime beats 97.89 % of javascript submissions
  • Your memory usage beats 5.01 % of javascript submissions (36.7 MB)
  • 時間複雜度 O(n)

查閱他人解法

查閱題解的過程中發現了以下幾種有意思的思路:

  • 動態規劃,使用增益的思路。其實上面我們寫的動態規劃是一樣的
  • 貪心法,嘗試多加一位,取較大值
  • 分治中使用貪心法求區間

Ⅰ.動態規劃

程式碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let res = nums[0]
    let sum = nums[0] // 增益
    for(let i = 1; i < nums.length; i++) {
        if (sum > 0) { // 正向增益, sum 保留並加上當前遍歷數字
            sum += nums[i]
        } else { // sum 更新為當前遍歷數字
            sum = nums[i]
        }
        res = Math.max(res, sum)
    }
    return res
};

結果:

  • 202/202 cases passed (60 ms)
  • Your runtime beats 97.89 % of javascript submissions
  • Your memory usage beats 47.5 % of javascript submissions (35.1 MB)
  • 時間複雜度 O(n)

Ⅱ.貪心法

程式碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let res = Number.MIN_SAFE_INTEGER // 初始值
    let sum = 0
    for(let i = 0; i < nums.length; i++) {
        sum += nums[i]
        res = Math.max(res, sum)
        if (sum < 0) { // 重新開始找子序串
            sum = 0;
        }
    }
    return res
};

結果:

  • 202/202 cases passed (68 ms)
  • Your runtime beats 90.14 % of javascript submissions
  • Your memory usage beats 45 % of javascript submissions (35.1 MB)
  • 時間複雜度 O(n)

Ⅲ.分治中使用貪心法求區間

程式碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    // 獲取跨邊界的和
    function getMaxCross (start, mid, end) {
        let leftRes = Number.MIN_SAFE_INTEGER
        let leftSum = 0
        for(let i = mid; i >= start; i--) {
            leftSum += nums[i]
            leftRes = Math.max(leftRes, leftSum)
        }

        let rightRes = Number.MIN_SAFE_INTEGER
        let rightSum = 0
        for(let i = mid + 1; i <= end; i++) {
            rightSum += nums[i]
            rightRes = Math.max(rightRes, rightSum)
        }

        return leftRes + rightRes
    }

    function countByDichotomy (start, end) {
        if (start === end) {
            return nums[start]
        } else {
            const mid = (start + end) >>> 1
            const leftSum = countByDichotomy(start, mid)
            const rightSum = countByDichotomy(mid + 1, end)
            const midSum = getMaxCross(start, mid, end)
            // 三者比較最大的就為最大子序和
            return Math.max(leftSum, rightSum, midSum)
        }
    }

    return countByDichotomy(0, nums.length - 1)
};

結果:

  • 202/202 cases passed (72 ms)
  • Your runtime beats 80.56 % of javascript submissions
  • Your memory usage beats 49.38 % of javascript submissions (35.1 MB)
  • 時間複雜度 O(nlog(n))

思考總結

個人認為動態規劃在這套題裡面解題思路清晰,貪心法也可以理解為基於遍歷基礎上做的延伸,而分治法需要畫圖加以理解。一般看到這種最大最長的題目,基本上就可以用動態規劃問題來嘗試作答了。

58.最後一個單詞的長度

題目地址

題目描述

給定一個僅包含大小寫字母和空格 ' ' 的字串,返回其最後一個單詞的長度。

如果不存在最後一個單詞,請返回 0

說明:一個單詞是指由字母組成,但不包含任何空格的字串。

示例:

輸入: "Hello World"
輸出: 5

題目分析設想

這道題看上去像是一道字串題,我們可以從以下幾個方面來嘗試作答:

  • 遍歷,從末尾開始,效率高
  • lastIndexOf,直接找空格
  • 正則
  • split

編寫程式碼驗證

Ⅰ.遍歷

程式碼:

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLastWord = function(s) {
    if(!s.length) return 0
    let i = s.length - 1
    while(i >= 0 && s.charAt(i) === ' ') {
        i--
    }
    if(i < 0) return 0 // 全是空格

    let j = i
    while(j >= 0 && s.charAt(j) != ' ') {
        j--
    }
    return i - j
};

結果:

  • 59/59 cases passed (64 ms)
  • Your runtime beats 81.14 % of javascript submissions
  • Your memory usage beats 29.72 % of javascript submissions (33.8 MB)
  • 時間複雜度 O(n)

Ⅱ.lastIndexOf

程式碼:

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLastWord = function(s) {
    if(!s.length) return 0
    s = s.trim()
    const idx = s.lastIndexOf(' ')
    return idx === -1 ? s.length : s.length - 1 - idx
};

結果:

  • 59/59 cases passed (48 ms)
  • Your runtime beats 99.48 % of javascript submissions
  • Your memory usage beats 36.52 % of javascript submissions (33.7 MB)
  • 時間複雜度 O(1)

Ⅲ.正則

程式碼:

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLastWord = function(s) {
    if(!s.length) return 0
    const match = s.match(/([a-zA-Z]+)\s*$/)
    let res = 0
    if (match) {
        res = match.pop()
        return res.length
    }
    return res
};

結果:

  • 59/59 cases passed (80 ms)
  • Your runtime beats 26.65 % of javascript submissions
  • Your memory usage beats 5.95 % of javascript submissions (34.2 MB)
  • 時間複雜度 O(1)

Ⅳ.split

程式碼:

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLastWord = function(s) {
    if(!s.length) return 0
    s = s.trim()
    const arr = s.split(' ')
    if (arr.length) {
        let str = arr.pop()
        return str.length
    } else {
        return 0
    }
};

結果:

  • 59/59 cases passed (60 ms)
  • Your runtime beats 90.57 % of javascript submissions
  • Your memory usage beats 13.8 % of javascript submissions (34 MB)
  • 時間複雜度 O(1)

查閱他人解法

沒有在題解中看到什麼特別的解法,大部分都是基於類庫解的,比如 JavascriptStringArray 的方法。或者是遍歷實現的。

思考總結

直到現在也沒有弄明白這道題的考察點在哪裡?不過我建議感興趣的同學,可以自己拓展實現 lastIndexOf ,參考 上一期 28題的數十種解法,應該能有不小收穫。

66.加一

題目地址

題目描述

給定一個由整陣列成的非空陣列所表示的非負整數,在該數的基礎上加一。

最高位數字存放在陣列的首位, 陣列中每個元素只儲存單個數字。

你可以假設除了整數 0 之外,這個整數不會以零開頭。

示例:

輸入: [1,2,3]
輸出: [1,2,4]
解釋: 輸入陣列表示數字 123。

輸入: [4,3,2,1]
輸出: [4,3,2,2]
解釋: 輸入陣列表示數字 4321。

題目分析設想

這道題我有兩個大方向,一是陣列遍歷進行求解,另外一種是陣列轉數字再處理。但是轉數字可能會溢位,所以就只想到從遍歷的角度來作答。

  • 遍歷,從後往前遍歷找到不為9的項,後面填0就可以了

編寫程式碼驗證

Ⅰ.遍歷

程式碼:

/**
 * @param {number[]} digits
 * @return {number[]}
 */
var plusOne = function(digits) {
    for(let i = digits.length - 1; i >= 0; i--) {
        // 找不到不為9的數,直接加1輸出就可以了
        if(digits[i] !== 9) {
            digits[i]++
            return digits
        } else {
            digits[i] = 0
        }
    }
    digits.unshift(1)
    return digits
};

結果:

  • 109/109 cases passed (60 ms)
  • Your runtime beats 93.72 % of javascript submissions
  • Your memory usage beats 26.35 % of javascript submissions (33.8 MB)
  • 時間複雜度 O(n)

查閱他人解法

發現思路基本都是遍歷,但是具體實現會有些差距,這裡只列舉一個最簡單的。

Ⅰ.遍歷

程式碼:

/**
 * @param {number[]} digits
 * @return {number[]}
 */
var plusOne = function(digits) {
    for(let i = digits.length - 1; i >= 0; i--) {
        digits[i]++
        // 取10的餘數,做了賦值操作,為0就繼續進位
        digits[i] %= 10
        if(digits[i] !== 0) {
            return digits
        }
    }
    digits.unshift(1)
    return digits
};

結果:

  • 109/109 cases passed (64 ms)
  • Your runtime beats 85.29 % of javascript submissions
  • Your memory usage beats 94.34 % of javascript submissions (33.4 MB)
  • 時間複雜度 O(n)

思考總結

這道題可能大眾的想法會轉成數字再處理,但是做數字運算的時候,千萬要記住考慮溢位的問題。另外因為是加1,所以倒序遍歷就可以了。至於是判斷末位為9還是對10取餘,我覺得都是一個很好理解的思路,也避免了程式碼的繁瑣。

(完)


本文為原創文章,可能會更新知識點及修正錯誤,因此轉載請保留原出處,方便溯源,避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗
如果能給您帶去些許幫助,歡迎 ⭐️star 或 ✏️ fork
(轉載請註明出處:https://chenjiahao.xyz)