」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 面試工具包:陣列 - 滑動視窗。

面試工具包:陣列 - 滑動視窗。

發佈於2024-11-06
瀏覽:712

一切都与模式有关!

一旦你学会了这些模式,一切都开始变得更容易了!如果你像我一样,你可能不喜欢技术面试,我不怪你——面试可能很艰难。

数组问题是面试中最常见的问题。这些问题通常涉及使用自然数组:

const arr = [1, 2, 3, 4, 5];

还有字符串问题,本质上是字符数组:

"mylongstring".split(""); // ['m', 'y', 'l', 'o','n', 'g', 's','t','r','i', 'n', 'g']


解决数组问题最常见的模式之一是滑动窗口

滑动窗口模式

滑动窗口模式涉及两个向同一方向移动的指针,就像在数组上滑动的窗口一样。

何时使用它

当您需要查找满足特定条件(例如最小值、最大值、最长或)的子数组子字符串时,请使用滑动窗口模式最短。

规则1:如果需要查找子数组或子字符串,并且数据结构是数组或字符串,请考虑使用滑动窗口模式。

简单的例子

下面通过一个基本例子来介绍滑动窗口中指针的概念:

function SlidingWindow(arr) {
    let l = 0;  // Left pointer
    let r = l   1;  // Right pointer

    while (r 



注意左(L)和右(R)指针不必同时移动,但必须朝同一方向移动。

Interview Kit: Arrays - Sliding window.

右指针永远不会低于左指针。

让我们通过一个真实的面试问题来探讨这个概念。

现实问题:不重复字符的最长子串

问题:给定一个字符串s,求不重复字符的最长子串的长度。

关键字: -字符串,最长(最大)

function longestSubstr(str) {
    let longest = 0;
    let left = 0;
    let hash = {};

    for (let right = 0; right = left) {
            left = hash[str[right]]   1;
        }

        hash[str[right]] = right;
        longest = Math.max(longest, right - left   1);
    }

    return longest;
}

如果这看起来很复杂,请不要担心——我们会一点一点地解释它。

let str = "helloworld";
console.log(longestSubstr(str));  // Output: 5

这个问题的核心是找到最长的子串没有重复字符。

初始窗口:大小 0

开始时,左(L)和右(R)指针都在同一个位置:

let left = 0;

for (let right = 0; right 





h e l l o w o r l d 
^
^
L
R

我们有一个空的哈希(对象):

let hash = {};

物体有什么伟大之处?它们存储唯一的密钥,这正是我们解决这个问题所需要的。我们将使用哈希来跟踪我们访问过的所有字符,并检查我们之前是否见过当前字符(以检测重复项)。

通过查看字符串,我们可以直观地看出world是最长的没有重复字符的子串:

h e l l o w o r l d 
          ^        ^   
          L        R

这个长度为 5。那么,我们如何到达那里?

我们一步步分解:

初始状态

hash = {}

h e l l o w o r l d 
^
^
L
R

迭代 1:

在每次迭代中,我们将 R 指针下的字符添加到哈希映射中并递增:

hash[str[right]] = right;
longest = Math.max(longest, right - left   1);

目前,我们的窗口中没有重复字符(h和e):

hash = {h: 0}
h e l l o w o r l d 
^ ^
L R

迭代 2:

hash = {h: 0, e: 1}
h e l l o w o r l d 
^   ^
L   R

现在,我们有一个新窗口:hel。

迭代 3:

hash = {h: 0, e: 1, l: 2}
h e l l o w o r l d 
^     ^
L     R

这就是有趣的地方:我们的哈希中已经有 l,而 R 指向字符串中的另一个 l。这就是我们的 if 语句出现的地方:

if (hash[str[right]] !== undefined)

如果我们的散列包含 R 指向的字母,我们就发现了一个重复项!上一个窗口 (hel) 是我们迄今为止最长的窗口。

那么,我们下一步该做什么?因为我们已经处理了左子串,所以我们通过向上移动 L 指针来从左侧缩小窗口。但我们要把 L 移动多远?

left = hash[str[right]]   1;

我们将 L 移到重复项之后:

hash = {h: 0, e: 1, l: 2}
h e l l o w o r l d 
      ^
      ^
      L
      R

我们仍然将重复项添加到哈希中,因此 L 现在的索引为 3。

hash[str[right]] = right;
longest = Math.max(longest, right - left   1);

新状态:迭代 4

hash = {h: 0, e: 1, l: 3}
h e l l o w o r l d 
      ^ ^
      L R

迭代 4 至 6

hash = {h: 0, e: 1, l: 3, o: 4, w: 5}
h e l l o w o r l d 
      ^     ^
      L     R

当 R 指向另一个重复项 (o) 时,我们将 L 移到第一个 o 之后:

hash = {h: 0, e: 1, l: 3, o: 4, w: 5}
h e l l o w o r l d 
          ^ ^
          L R

我们继续,直到遇到另一个重复的 l:

hash = {h: 0, e: 1, l: 3, o: 4, w: 5, o: 6, r: 7}
h e l l o w o r l d 
          ^     ^
          L     R

但是请注意它在当前窗口之外!从w开始,

规则 3:忽略已处理的子 x

当前窗口之外的任何内容都是无关紧要的——我们已经处理了它。管理这个的关键代码是:

if (hash[str[right]] !== undefined && hash[str[right]] >= left)

这个条件确保我们只关心当前窗口内的字符,过滤掉任何噪音。

hash[str[right]] >= left

我们关注任何大于或等于左指针的东西

最终迭代:

hash = {h: 0, e: 1, l: 8, o: 4, w: 5, o: 6, r: 7}
h e l l o w o r l d 
          ^       ^
          L       R

我知道这很详细,但是将问题分解为更小的模式或规则是掌握它们的最简单方法。

总之:

  • 规则1:问题中的关键词(例如最大值、最小值)是线索。本题是求最长的子串不带重复字符。
  • 规则 2: 如果您需要查找唯一或不重复的元素,请考虑哈希映射。
  • 规则 3: 关注当前窗口——窗口之外的任何内容都是无关紧要的。

奖金提示:

  • 使用一个小子集分解问题并使其变得冗长。
  • 最大化当前窗口时,考虑如何使其尽可能长。反之,最小化的时候,想想如何让它尽可能的小。

最后,这里有一个小挑战供您尝试!我将在评论中发布我的解决方案 - 这是一种很好的练习方式。

问题 2:总和大于或等于目标

给定一个数组,找到总和等于或大于目标的最小子数组(我的解决方案将是第一个注释)。

/**
 * 
 * @param {Array} arr 
 * @param {number} target 
 * @returns {number} - length of the smallest subarray
 */
function greaterThanOrEqualSum(arr, target){
   let minimum = Infinity;
   let left = 0;
   let sum = 0;

   // Your sliding window logic here!
}

记住,就像编程中的任何事情一样,重复是关键!滑动窗口问题总是会出现,所以不要犹豫,谷歌更多的例子并继续练习。

我的这篇文章很简短,但请继续关注——下一篇文章将深入探讨两指针模式和递归(为树问题做准备)。这将会更具挑战性!

如果您想要更多独家内容,您可以在 Twitter 或 Ko-fi 上关注我,我会在那里发布一些额外的内容!

资源:

技术面试手册

leet代码数组101

版本聲明 本文轉載於:https://dev.to/sfundomhlungu/interview-kit-arrays-sliding-window-9hd?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何高效地在一個事務中插入數據到多個MySQL表?
    如何高效地在一個事務中插入數據到多個MySQL表?
    mySQL插入到多個表中,該數據可能會產生意外的結果。雖然似乎有多個查詢可以解決問題,但將從用戶表的自動信息ID與配置文件表的手動用戶ID相關聯提出了挑戰。 使用Transactions和last_insert_id() 插入用戶(用戶名,密碼)值('test','tes...
    程式設計 發佈於2025-05-07
  • 如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    為有效的slug生成首先,該函數用指定的分隔符替換所有非字母或數字字符。此步驟可確保slug遵守URL慣例。隨後,它採用ICONV函數將文本簡化為us-ascii兼容格式,從而允許更廣泛的字符集合兼容性。 接下來,該函數使用正則表達式刪除了不需要的字符,例如特殊字符和空格。此步驟可確保slug僅包...
    程式設計 發佈於2025-05-07
  • 如何從Google API中檢索最新的jQuery庫?
    如何從Google API中檢索最新的jQuery庫?
    從Google APIS 問題中提供的jQuery URL是版本1.2.6。對於檢索最新版本,以前有一種使用特定版本編號的替代方法,它是使用以下語法:獲取最新版本:未壓縮)While these legacy URLs still remain in use, it is recommended ...
    程式設計 發佈於2025-05-07
  • Python高效去除文本中HTML標籤方法
    Python高效去除文本中HTML標籤方法
    在Python中剝離HTML標籤,以獲取原始的文本表示Achieving Text-Only Extraction with Python's MLStripperTo streamline the stripping process, the Python standard librar...
    程式設計 發佈於2025-05-07
  • 如何在鼠標單擊時編程選擇DIV中的所有文本?
    如何在鼠標單擊時編程選擇DIV中的所有文本?
    在鼠標上選擇div文本單擊帶有文本內容,用戶如何使用單個鼠標單擊單擊div中的整個文本?這允許用戶輕鬆拖放所選的文本或直接複製它。 在單個鼠標上單擊的div元素中選擇文本,您可以使用以下Javascript函數: function selecttext(canduterid){ if(d...
    程式設計 發佈於2025-05-07
  • 如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    從python import codecs import codecs import codecs 導入 text = codecs.decode('這狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#帶有...
    程式設計 發佈於2025-05-07
  • 在細胞編輯後,如何維護自定義的JTable細胞渲染?
    在細胞編輯後,如何維護自定義的JTable細胞渲染?
    在JTable中維護jtable單元格渲染後,在JTable中,在JTable中實現自定義單元格渲染和編輯功能可以增強用戶體驗。但是,至關重要的是要確保即使在編輯操作後也保留所需的格式。 在設置用於格式化“價格”列的“價格”列,用戶遇到的數字格式丟失的“價格”列的“價格”之後,問題在設置自定義單元...
    程式設計 發佈於2025-05-07
  • 如何同步迭代並從PHP中的兩個等級陣列打印值?
    如何同步迭代並從PHP中的兩個等級陣列打印值?
    同步的迭代和打印值來自相同大小的兩個數組使用兩個數組相等大小的selectbox時,一個包含country代碼的數組,另一個包含鄉村代碼,另一個包含其相應名稱的數組,可能會因不當提供了exply for for for the uncore for the forsion for for ytry...
    程式設計 發佈於2025-05-07
  • 如何在Java字符串中有效替換多個子字符串?
    如何在Java字符串中有效替換多個子字符串?
    在java 中有效地替換多個substring,需要在需要替換一個字符串中的多個substring的情況下,很容易求助於重複應用字符串的刺激力量。 However, this can be inefficient for large strings or when working with nu...
    程式設計 發佈於2025-05-07
  • 如何修復\“常規錯誤:2006 MySQL Server在插入數據時已經消失\”?
    如何修復\“常規錯誤:2006 MySQL Server在插入數據時已經消失\”?
    How to Resolve "General error: 2006 MySQL server has gone away" While Inserting RecordsIntroduction:Inserting data into a MySQL database can...
    程式設計 發佈於2025-05-07
  • 如何使用PHP將斑點(圖像)正確插入MySQL?
    如何使用PHP將斑點(圖像)正確插入MySQL?
    essue VALUES('$this->image_id','file_get_contents($tmp_image)')";This code builds a string in PHP, but the function call fil...
    程式設計 發佈於2025-05-07
  • PHP未來:適應與創新
    PHP未來:適應與創新
    PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。 引言在編程世界中,PHP一直是網頁開發的中流砥柱。作為一個從1994年就開始發展...
    程式設計 發佈於2025-05-07
  • 為什麼不````''{margin:0; }`始終刪除CSS中的最高邊距?
    為什麼不````''{margin:0; }`始終刪除CSS中的最高邊距?
    在CSS 問題:不正確的代碼: 全球範圍將所有餘量重置為零,如提供的代碼所建議的,可能會導致意外的副作用。解決特定的保證金問題是更建議的。 例如,在提供的示例中,將以下代碼添加到CSS中,將解決餘量問題: body H1 { 保證金頂:-40px; } 此方法更精確,避免了由全局保證金重置...
    程式設計 發佈於2025-05-07
  • FastAPI自定義404頁面創建指南
    FastAPI自定義404頁面創建指南
    response = await call_next(request) if response.status_code == 404: return RedirectResponse("https://fastapi.tiangolo.com") else: ...
    程式設計 發佈於2025-05-07
  • 使用jQuery如何有效修改":after"偽元素的CSS屬性?
    使用jQuery如何有效修改":after"偽元素的CSS屬性?
    在jquery中了解偽元素的限制:訪問“ selector 嘗試修改“:”選擇器的CSS屬性時,您可能會遇到困難。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    程式設計 發佈於2025-05-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3