JS: 數據結構與演算法之棧

来源:https://www.cnblogs.com/guolao/archive/2019/01/16/10279383.html
-Advertisement-
Play Games

棧 先來看一道題 Leetcode 32 Longest Valid Parentheses (最長有效括弧) 給定一個只包含 和 的字元串,找出最長的包含有效括弧的子串的長度。 示例 1: 示例 2: 這道題可以用動態規劃來做,也能用簡潔明瞭的棧來解決。 什麼是棧? 棧是一種先進後出(LIFO)的 ...


先來看一道題


Leetcode 32 Longest Valid Parentheses (最長有效括弧)

給定一個只包含 '('')' 的字元串,找出最長的包含有效括弧的子串的長度。

示例 1:

輸入: "(()"
輸出: 2
解釋: 最長有效括弧子串為 "()"

示例 2:

輸入: ")()())"
輸出: 4
解釋: 最長有效括弧子串為 "()()"

這道題可以用動態規劃來做,也能用簡潔明瞭的棧來解決。

什麼是棧?


棧是一種先進後出(LIFO)的有序集合,新添加的元素在棧頂,舊元素在棧底。

以下圖為例,1、2、3、4、5、6、7先後進棧:

創建棧


創建一個類來表示棧:

class Stack {
    // 初始化類,創建數組 items 存放入棧元素
    constructor() {
        this.items = [];
    }
    // push 方法進行元素入棧(可同時入棧一或多個元素),無返回值
    push() {
        this.items.push(...arguments);
    }
    // pop 方法出棧一個元素,返回出棧元素
    pop() {
        return this.items.pop();
    }
    // peek 方法返回棧頂元素,不對棧本身做任何操作
    peek() {
        return this.items[this.items.length-1];
    }
    // size 方法返回棧內元素個數
    size() {
        return this.items.length;
    }
    // isEmpty 方法查看棧是否為空,返回布爾值
    isEmpty() {
        return this.items.length == 0;
    }
    // clear 方法清空棧,無返回值
    clear() {
        this.items = [];
    }
    // print 方法列印棧內元素
    print() {
        console.log(this.items.toString());
    }
}

// 測試 
let stack = new Stack();
stack.push(1,2,3,4);
stack.print(); // 1,2,3,4
stack.isEmpty(); // false
stack.size(); // 4
stack.pop(); // 4
stack.peek(); // 3
stack.clear();

註意


因為 JavaScript 的類內暫時無法定義靜態成員,所以可以在類外訪問到存儲棧元素的數組 items,這個操作是很危險的。

stack.items; // [1, 2, 3, 4]

這時可以使用閉包IIFE進行避免,這是一個很無奈的辦法:

let Stack = (function () {
    // 使用 WeakMap 存儲數組(數組存放進棧元素)
    let items = new WeakMap();
    class Stack {
        constructor() {
            items.set(this, []);
        }
        push() {
            items.get(this).push(...arguments);
        }
        // 其他方法
    }
    return Stack;
})();

let s = new Stack();
// 無法訪問到 items
s.items; // undefined

WeakMap: WeakMap是類似Map的鍵值對集合,但WeakMap的鍵是弱引用的,只要不存在引用,垃圾回收機制就會回收掉占用的記憶體,相當於自動刪除,而不用手動刪除。

用棧解題


思路:

  1. 變數start存放有效括弧起始下標,maxLen存放最大長度;
  2. 棧只存放左括弧的下標,遇到左括弧,將其下標存入棧中;
  3. 遇到右括弧,若此時棧為空,跳過本次迴圈並更新start;若棧不為空,則棧頂元素出棧;
  4. 棧頂元素出棧後,若棧為空,則計算當前下標和start的距離,並更新maxLen
  5. 棧頂元素出棧後,若棧不為空,則計算當前下標和棧頂存放的下標的距離,並更新maxLen
  6. 迴圈遍歷直至結束。
function test(str) {
    let stack = new Stack();
    let start = 0;
    let maxLen = 0;

    for(let i=0; i<str.length; i++) {
        // 如果是左括弧,下標入棧
        if (str[i] == '(') {
            stack.push(i);
        } else {
            // 如果是右括弧
            /* 棧內為空,說明本次有效括弧匹配已結束,跳過本次迴圈並更新 start */
            if (stack.isEmpty()) {
                start = i+1;
                continue;
            } else {
                // 棧內不為空,則出棧一個左括弧進行匹配
                stack.pop();
                // 棧頂元素出棧後,棧為空
                if (stack.isEmpty()) {
                    // 根據當前下標和 start 去更新 maxLen
                    maxLen = Math.max(maxLen, i-start+1);
                } else {
                    // 棧不為空,根據當前下標和棧頂存放的下標去更新 maxLen
                    maxLen = Math.max(maxLen, i-stack.peek());
                }
                
            }
        }       
    }
    
    return maxLen;
}

test('(()'); // 2
test(')()())'); // 4

備註


終於從大半個月的考試和課設中解放出來了,每天早起晚睡,還是很累的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 嵌套標簽我們已經講一次了,在0X4.1里,我們把列表嵌套了 你覺得文字鏈接難看得令人作嘔,好,你再也不會有這種感覺了 一如既往,一個html文件和一個存放圖片的文件夾 index.html的代碼,很簡單 1 <html> 2 <head> 3 <title>TEST</title> 4 </head ...
  • 校驗基本日期格式: var reg = /^(\\d{1,4})(-|\\/)(\\d{1,2})\\2(\\d{1,2})$/; var r = fieldValue.match(reg); if (r==null) { alert('Date format error!'); } 校驗基本日期格 ...
  • a標簽不只是能鏈接到其他網頁,也能鏈接到網頁中的元素 class屬性讓你用CSS對特定的元素進行修飾 這些是一個網頁設計者的有力武器 這節課還是一個index.html文件 以下是代碼 以下是代碼 1 <html> 2 <head> 3 <title>TEST</title> 4 </head> 5 ...
  • 如果你認為列表只有ul和ol那你就錯了 我要為你展示新的列表 這次只有一個index.html文件 這是它的效果 以下是它的代碼 1 <html> 2 <head> 3 <title>TEST</title> 4 </head> 5 <body> 6 <!--嵌套列表--> 7 <p> 8 嵌套列表 ...
  • 想讓你的網頁變得整潔嗎?找我就對了,當然你會認識幾個新元素,和它們交朋友吧! 我幫你聯繫一下這幾個新元素,這樣交朋友就變得簡單了 images里放著圖片 以下是index.html的代碼 1 <html> 2 <head> 3 <title>Sagway'n USA</title> 4 </head ...
  • JS面向對象系列教程 — 對象的基本操作 面向對象概述  面向對象(Object Oriented)簡稱OO,它是一種編程思維,用於指導我們如何應對各種複雜的開發場景。 這裡說的對象(Object),意思就是事物,在面向對象的思維中,它將一切都看作是對象,並以對象為切入點去思考問題。 使用面向對象 ...
  • 沒有頭腦的管理方式會釀成大災難,應該使用文件夾管理網站 這是一個典型的管理方法,現在傳授給你,聽好了 下麵是0x3初識a標簽里使用的網站的目錄,我把它重新配置了一下 這是包含網站的文件夾 這是網站的根目錄 原來的directions.html放在about文件夾 原來的elixir.html放在be ...
  • 1、當選擇器選擇多個元素時,每個元素都會觸發一次回調函數,但是如果回調函數後有括弧(2、3),則只會執行一次,而1、4會執行多次。 2、如果回調函數後有括弧(2,3),則函數會立即執行,而不是在顯示/隱藏完成後在執行(1、4)。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...