欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

TypeScript數(shù)據(jù)結(jié)構(gòu)之隊列結(jié)構(gòu)Queue教程示例

 更新時間:2023年02月05日 10:37:28   作者:前端要努力QAQ  
這篇文章主要為大家介紹了TypeScript數(shù)據(jù)結(jié)構(gòu)之隊列結(jié)構(gòu)Queue教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

1. 認(rèn)識隊列結(jié)構(gòu)

隊列是一個 先進(jìn)先出(FIFO) 的數(shù)據(jù)結(jié)構(gòu)

js 中沒有隊列,但我們可以用 數(shù)組或鏈表 實現(xiàn)隊列的所有功能

隊列的常用操作:

enqueue(element):向隊列尾部添加一個(多個)新的項

dequeue():移除隊列的第一項,并返回被移除的元素

front/peek():返回隊列中的第一個元素

isEmpty():判斷隊列是否為空

size():返回隊列的元素個數(shù)

隊列的結(jié)構(gòu)示意圖:

2. 實現(xiàn)隊列結(jié)構(gòu)封裝

隊列的實現(xiàn)和棧一樣也有兩種實現(xiàn)方式:

  • 基于 數(shù)組 實現(xiàn)
  • 基于 鏈表 實現(xiàn)

鏈表也是一種數(shù)據(jù)結(jié)構(gòu),js 中沒有自帶鏈表結(jié)構(gòu),后續(xù)會寫關(guān)于鏈表的文章,本章先使用數(shù)組來實現(xiàn)。

實現(xiàn):

// 封裝一個隊列
export default class ArrayQueue<T = any> {
  private data: T[] = [];
  constructor(data: T[]) {
    this.data = data || [];
  }
  enqueue(element: T): void {
    this.data.push(element);
  }
  dequeue(): T | undefined {
    return this.data.shift();
  }
  peek(): T | undefined {
    return this.data[0];
  }
  isEmpty(): boolean {
    return this.data.length === 0;
  }
  size(): number {
    return this.data.length;
  }
}

測試:

const queue = new ArrayQueue<number>();
queue.push(1);
queue.push(2);
queue.pop();
queue.push(3);
console.log(queue); // ArrayQueue { data: [ 2, 3 ] }

3. 實戰(zhàn)一:最近的請求次數(shù)

這是 Leetcode 上的第 933 道題,難度為 簡單

3.1 題目描述

寫一個 RecentCounter 類來計算特定時間范圍內(nèi)最近的請求。

請你實現(xiàn) RecentCounter 類:

  • RecentCounter() 初始化計數(shù)器,請求數(shù)為 0 。
  • int ping(int t) 在時間 t 添加一個新請求,其中 t 表示以毫秒為單位的某個時間,并返回過去 3000 毫秒內(nèi)發(fā)生的所有請求數(shù)(包括新請求)。確切地說,返回在 [t-3000, t] 內(nèi)發(fā)生的請求數(shù)。

保證 每次對 ping 的調(diào)用都使用比之前更大的 t 值。

示例 1:

輸入:
["RecentCounter", "ping", "ping", "ping", "ping"]
[[], [1], [100], [3001], [3002]]
輸出:
[null, 1, 2, 3, 3]
解釋:
RecentCounter recentCounter = new RecentCounter();
recentCounter.ping(1);     // requests = [1],范圍是 [-2999,1],返回 1
recentCounter.ping(100);   // requests = [1, 100],范圍是 [-2900,100],返回 2
recentCounter.ping(3001);  // requests = [1, 100, 3001],范圍是 [1,3001],返回 3
recentCounter.ping(3002);  // requests = [1, 100, 3001, 3002],范圍是 [2,3002],返回 3

提示:

  • 1 <= t <= 109
  • 保證每次對 ping 調(diào)用所使用的 t 值都 嚴(yán)格遞增
  • 至多調(diào)用 ping 方法 104 次

3.2 解一:隊列

思路:

我們可以用一個隊列維護(hù)發(fā)生請求的時間,當(dāng)在時間 t 收到請求時,將時間 t 入隊。 保證隊列的 尾部值 減去隊列的 首部值 小于等于 3000,隊列中的元素數(shù)量即為 最近的請求次數(shù)

代碼:

class RecentCounter {
  queue: ArrayQueue<number>;
  constructor() {
    this.queue = new ArrayQueue<number>();
  }
  ping(t: number): number {
    this.queue.enqueue(t);
    while (this.queue.peek() < t - 3000) {
      this.queue.dequeue();
    }
    return this.queue.size();
  }
}
/**
 * Your RecentCounter object will be instantiated and called as such:
 * var obj = new RecentCounter()
 * var param_1 = obj.ping(t)
 */

復(fù)雜度分析:

時間復(fù)雜度:均攤 O(1),每個元素至多入隊出隊各一次。

空間復(fù)雜度:O(L),其中 L 為隊列的最大元素個數(shù)。

4. 實戰(zhàn)二:無法吃午餐的學(xué)生數(shù)量

這是 Leetcode 上的第 1700 道題,難度為 簡單

4.1 題目描述

學(xué)校的自助午餐提供圓形和方形的三明治,分別用數(shù)字 0 和 1 表示。所有學(xué)生站在一個隊列里,每個學(xué)生要么喜歡圓形的要么喜歡方形的。
餐廳里三明治的數(shù)量與學(xué)生的數(shù)量相同。所有三明治都放在一個 棧 里,每一輪:

  • 如果隊列最前面的學(xué)生 喜歡 棧頂?shù)娜髦危敲磿?nbsp;拿走它 并離開隊列。
  • 否則,這名學(xué)生會 放棄這個三明治 并回到隊列的尾部。

這個過程會一直持續(xù)到隊列里所有學(xué)生都不喜歡棧頂?shù)娜髦螢橹埂?/p>

給你兩個整數(shù)數(shù)組 students 和 sandwiches ,其中 sandwiches[i] 是棧里面第 i?????? 個三明治的類型(i = 0 是棧的頂部), students[j] 是初始隊列里第 j?????? 名學(xué)生對三明治的喜好(j = 0 是隊列的最開始位置)。請你返回?zé)o法吃午餐的學(xué)生數(shù)量。

示例 1:

輸入: students = [1,1,0,0], sandwiches = [0,1,0,1]
輸出: 0 解釋:
- 最前面的學(xué)生放棄最頂上的三明治,并回到隊列的末尾,學(xué)生隊列變?yōu)?students = [1,0,0,1]。
- 最前面的學(xué)生放棄最頂上的三明治,并回到隊列的末尾,學(xué)生隊列變?yōu)?students = [0,0,1,1]。
- 最前面的學(xué)生拿走最頂上的三明治,剩余學(xué)生隊列為 students = [0,1,1],三明治棧為 sandwiches = [1,0,1]。
- 最前面的學(xué)生放棄最頂上的三明治,并回到隊列的末尾,學(xué)生隊列變?yōu)?students = [1,1,0]。
- 最前面的學(xué)生拿走最頂上的三明治,剩余學(xué)生隊列為 students = [1,0],三明治棧為 sandwiches = [0,1]。
- 最前面的學(xué)生放棄最頂上的三明治,并回到隊列的末尾,學(xué)生隊列變?yōu)?students = [0,1]。
- 最前面的學(xué)生拿走最頂上的三明治,剩余學(xué)生隊列為 students = [1],三明治棧為 sandwiches = [1]。
- 最前面的學(xué)生拿走最頂上的三明治,剩余學(xué)生隊列為 students = [],三明治棧為 sandwiches = []。
所以所有學(xué)生都有三明治吃。

示例 2:

輸入: students = [1,1,1,0,0,1], sandwiches = [1,0,0,0,1,1]
輸出: 3

提示:

  • 1 <= students.length, sandwiches.length <= 100
  • students.length == sandwiches.length
  • sandwiches[i] 要么是 0 ,要么是 1 。
  • students[i] 要么是 0 ,要么是 1 。

4.2 解一:隊列

思路: 我們可以維護(hù)兩個隊列,一個是學(xué)生隊列,一個是三明治隊列。

循環(huán)比較 學(xué)生隊列三明治隊列 的 頭部第一個元素,如果相同則都 移除 它們,如果不相同則將學(xué)生隊列的頭部元素移到尾部,直到碰到下一組相同的兩個頭部元素 或者 學(xué)生隊列所有學(xué)生都不喜歡三明治隊列的第一個三明治。

代碼:

function countStudents(students: number[], sandwiches: number[]): number {
  const studentsQueue = new ArrayQueue<number>(students);
  const sandwichesQueue = new ArrayQueue<number>(sandwiches);
  let count = 0;
  while (studentsQueue.size()) {
    if (studentsQueue.peek() === sandwichesQueue.peek()) {
      studentsQueue.dequeue();
      sandwichesQueue.dequeue();
      count = 0;
    } else {
      studentsQueue.enqueue(studentsQueue.dequeue()!);
      count++;
    }
    if (count === studentsQueue.size()) return sandwichesQueue.size();
  }
  return 0;
}

復(fù)雜度分析

  • 時間復(fù)雜度:O(n),其中 n 是學(xué)生的數(shù)量。
  • 空間復(fù)雜度:O(1)。

5. 實戰(zhàn)三:字符串中的第一個唯一字符

這是 Leetcode 上的第 387 道題,難度為 簡單

5.1 題目描述

給定一個字符串 s ,找到 它的第一個不重復(fù)的字符,并返回它的索引 。如果不存在,則返回 -1 。

示例 1:

輸入: s = "leetcode"
輸出: 0

示例 2:

輸入: s = "loveleetcode"
輸出: 2

示例 3:

輸入: s = "aabb"
輸出: -1

提示:

  • 1 <= s.length <= 105
  • s 只包含小寫字母

5.2 解一:哈希表

思路:

維護(hù)一個 map,分兩次遍歷字符串

  • 第一次遍歷存儲每個字符對應(yīng)的出現(xiàn)次數(shù)
  • 第二次遍歷取出第一個只出現(xiàn)第一次的字符

代碼:

function firstUniqChar(s: string): number {
  const map = new Map<string, number>();
  for (let i = 0; i < s.length; i++) {
    let n = map.get(s[i]);
    n ? map.set(s[i], n + 1) : map.set(s[i], 1);
  }
  for (let i = 0; i < s.length; i++) {
    if (map.get(s[i]) === 1) return i;
  }
  return -1;
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(∣Σ∣),其中 Σ 是字符集,在本題中 s 只包含小寫字母,因此 ∣Σ∣≤26 。我們需要 O(∣Σ∣) 的空間存儲哈希映射。

5.3 解二:隊列

思路:

維護(hù)一個隊列,按照順序存儲每一個字符以及它們第一次出現(xiàn)的位置。當(dāng)我們對字符串進(jìn)行遍歷時,設(shè)當(dāng)前遍歷到的字符為 c,如果 c 不在哈希映射中,我們就將 c 與它的索引作為一個二元組放入隊尾,否則我們就需要檢查隊列中的元素是否都滿足「只出現(xiàn)一次 的要求,即我們不斷地根據(jù)哈希映射中存儲的值(是否為 −1)選擇彈出隊首的元素,直到隊首元素 「真的」 只出現(xiàn)了一次或者隊列為空。

在遍歷完成后,如果隊列為空,說明沒有不重復(fù)的字符,返回 −1,否則隊首的元素即為第一個不重復(fù)的字符以及其索引的二元組

代碼:

function firstUniqChar(s: string): number {
  const map = new Map<string, number>();
  const queue = new ArrayQueue<[string, number]>();
  for (let i = 0; i < s.length; i++) {
    if(!map.has(s[i])) {
      map.set(s[i], i)
      queue.enqueue([s[i], i]);
    } else {
      map.set(s[i], -1)
      while(queue.size() && map.get((queue.peek() as [string,number])[0]) === -1) {
        queue.dequeue()
      }
    }
  }
  return queue.size() ? (queue.peek() as [string, number])[1] : -1;
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(∣Σ∣)

以上就是TypeScript數(shù)據(jù)結(jié)構(gòu)之隊列結(jié)構(gòu)Queue教程示例的詳細(xì)內(nèi)容,更多關(guān)于TypeScript 隊列結(jié)構(gòu)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • CKEditor4配置與開發(fā)詳細(xì)中文說明文檔

    CKEditor4配置與開發(fā)詳細(xì)中文說明文檔

    網(wǎng)上分享的CKEditor4中文說明很多都只是的部分使用方法,今天為大家分享一下比較完整的CKEditor4中文說明文檔
    2018-10-10
  • TypeScript類型操作之字符串處理功能詳解

    TypeScript類型操作之字符串處理功能詳解

    這篇文章主要為大家介紹了TypeScript類型操作之字符串處理功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • typescript 支持與本地調(diào)試配置詳解

    typescript 支持與本地調(diào)試配置詳解

    這篇文章主要為大家介紹了typescript 支持與本地調(diào)試配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • TypeScript使用noImplicitAny實戰(zhàn)解析

    TypeScript使用noImplicitAny實戰(zhàn)解析

    這篇文章主要為大家介紹了TypeScript使用noImplicitAny實戰(zhàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • PureScript與JavaScript中equality設(shè)計的使用對比分析

    PureScript與JavaScript中equality設(shè)計的使用對比分析

    這篇文章主要為大家介紹了PureScript中的equality與JavaScript中的equality設(shè)計對比分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 前端算法之TypeScript包含min函數(shù)的棧實例詳解

    前端算法之TypeScript包含min函數(shù)的棧實例詳解

    這篇文章主要為大家介紹了前端算法之TypeScript包含min函數(shù)的棧實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • TypeScript逆變之條件推斷和泛型的應(yīng)用示例詳解

    TypeScript逆變之條件推斷和泛型的應(yīng)用示例詳解

    這篇文章主要為大家介紹了TypeScript逆變之條件推斷和泛型的應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • TypeScript十大排序算法插入排序?qū)崿F(xiàn)示例詳解

    TypeScript十大排序算法插入排序?qū)崿F(xiàn)示例詳解

    這篇文章主要為大家介紹了TypeScript十大排序算法插入排序?qū)崿F(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Three.js?粗糙度貼圖與金屬度貼圖使用介紹

    Three.js?粗糙度貼圖與金屬度貼圖使用介紹

    這篇文章主要為大家介紹了Three.js?粗糙度貼圖與金屬度貼圖使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • typescript快速上手的基礎(chǔ)知識篇

    typescript快速上手的基礎(chǔ)知識篇

    靜態(tài)類型的typescript與傳統(tǒng)動態(tài)弱類型語言javascript不同,在執(zhí)行前會先編譯成javascript,因為它強(qiáng)大的type類型系統(tǒng)加持,能讓我們在編寫代碼時增加更多嚴(yán)謹(jǐn)?shù)南拗?。注意,它并不是一門全新的語言,所以并沒有增加額外的學(xué)習(xí)成本
    2022-12-12

最新評論