LeetCode 443 壓縮字符串

字符數組壓縮算法詳解:實現與分析

一、引言

在處理字符數組時,我們常常遇到需要對連續重復字符進行壓縮的場景。這不僅可以節省存儲空間,還能提升數據傳輸效率。本文將深入解析一個經典的字符數組壓縮算法,通過詳細的實現步驟和原理分析,幫助讀者全面理解這一算法。

二、問題詳細描述

給定一個字符數組 chars,請使用以下算法進行壓縮:

  1. 從一個空字符串 s 開始。

  2. 對于 chars 中的每組連續重復字符:

    • 如果這一組長度為 1,則將字符追加到 s 中。

    • 否則,需要向 s 追加字符,后跟這一組的長度。例如,字符 'a' 連續出現 3 次,則壓縮為 "a3"

  3. 壓縮后得到的字符串 s 不應該直接返回,需要轉儲到字符數組 chars 中。如果組長度為 10 或 10 以上,則在 chars 數組中會被拆分為多個字符。例如,長度為 12 的組將被寫為 '1''2' 兩個字符。

  4. 修改完輸入數組后,返回該數組的新長度。

三、解題思路:雙指針法

3.1 算法原理

為了高效地在原地完成字符數組的壓縮,我們采用雙指針技術。雙指針法通過兩個指針 readwrite 分別負責讀取和寫入操作,能夠在一次遍歷中完成壓縮,無需額外的空間。

3.2 詳細步驟

  1. 初始化指針readwrite 指針都從 0 開始。

  2. 讀取字符read 指針用于遍歷字符數組,找到每組連續重復字符。

  3. 計數:對于每個字符,計算其連續出現的次數。這通過一個循環實現,每次檢查下一個字符是否與當前字符相同,如果是,則計數加 1。

  4. 寫入字符:將當前字符寫入 write 指針位置。然后根據計數決定是否需要寫入數字。

  5. 寫入計數:如果計數大于 1,則將計數轉換為字符串,并逐個字符寫入 write 指針后續位置。例如,計數為 12 時,寫入 '1''2'

  6. 移動指針read 指針移動到下一組字符的起始位置,write 指針根據寫入的字符數量移動。

3.3 優勢

雙指針法的優勢在于:

  • 高效性:僅需一次遍歷即可完成壓縮,時間復雜度為 O(n),其中 n 是數組長度。

  • 空間效率:所有操作在原數組上進行,無需額外存儲結構,空間復雜度為 O(1)。

四、算法實現

以下是 Java 實現代碼:

class Solution {public int compress(char[] chars) {if (chars == null || chars.length == 0) return 0;int write = 0;int n = chars.length;for (int read = 0; read < n; ) {char current = chars[read];int count = 1;// 計算連續字符的長度while (read + count < n && chars[read + count] == current) {count++;}// 寫入當前字符chars[write++] = current;// 如果計數大于 1,寫入計數if (count > 1) {String s = String.valueOf(count);for (char c : s.toCharArray()) {chars[write++] = c;}}// 移動讀取指針到下一組字符read += count;}return write;}
}

五、代碼詳細解析

5.1 初始化

if (chars == null || chars.length == 0) return 0;
int write = 0;
int n = chars.length;
  • 首先檢查輸入數組是否為空或長度為 0。如果是,則直接返回 0。

  • 初始化 write 指針為 0,用于跟蹤寫入位置。

  • 獲取數組長度 n,用于后續循環控制。

5.2 外層循環:遍歷字符數組

for (int read = 0; read < n; ) {char current = chars[read];int count = 1;
  • read 指針從 0 開始,遍歷整個數組。

  • 對于每個 read 位置的字符,將其存儲在 current 中,并初始化計數為 1。

5.3 內層循環:計算連續字符長度

while (read + count < n && chars[read + count] == current) {count++;
}
  • 檢查 read + count 是否在數組范圍內,并且下一個字符是否與 current 相同。

  • 如果是,則計數加 1,直到遇到不同的字符或數組末尾。

5.4 寫入字符

chars[write++] = current;
  • 將當前字符寫入 write 指針位置,并將 write 指針向前移動一位。

5.5 寫入計數

if (count > 1) {String s = String.valueOf(count);for (char c : s.toCharArray()) {chars[write++] = c;}
}
  • 如果計數大于 1,則將計數轉換為字符串。

  • 遍歷字符串的每個字符,并將其逐個寫入數組。例如,計數為 12 時,寫入 '1''2'

5.6 移動讀取指針

read += count;
  • read 指針移動到下一組字符的起始位置,繼續處理下一組字符。

六、算法分析

6.1 時間復雜度

該算法的時間復雜度為 O(n),其中 n 是字符數組的長度。每個字符僅被處理一次,無論是讀取還是寫入操作。內層循環雖然看似增加了復雜度,但實際上每個字符只被檢查一次,因此總的時間復雜度仍然是線性的。

6.2 空間復雜度

空間復雜度為 O(1),因為我們沒有使用任何與輸入規模相關的額外存儲結構。所有操作都在原數組上進行,僅使用了幾個變量來輔助操作。

七、示例分析

示例 1

輸入chars = ['a', 'a', 'b', 'b', 'c', 'c', 'c']

步驟解析

  1. read = 0current = 'a',計數為 2。

    • 寫入 'a'write = 1

    • 寫入 '2'write = 2

    • read 移動到 2。

  2. read = 2current = 'b',計數為 2。

    • 寫入 'b'write = 3

    • 寫入 '2'write = 4

    • read 移動到 4。

  3. read = 4current = 'c',計數為 3。

    • 寫入 'c'write = 5

    • 寫入 '3'write = 6

    • read 移動到 7,循環結束。

輸出:數組變為 ['a', '2', 'b', '2', 'c', '3'],新長度為 6。

示例 2

輸入chars = ['a']

步驟解析

  1. read = 0current = 'a',計數為 1。

    • 寫入 'a'write = 1

    • 因為計數為 1,不寫入數字。

    • read 移動到 1,循環結束。

輸出:數組仍為 ['a'],新長度為 1。

示例 3

輸入chars = ['a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']

步驟解析

  1. read = 0current = 'a',計數為 1。

    • 寫入 'a'write = 1

    • read 移動到 1。

  2. read = 1current = 'b',計數為 12。

    • 寫入 'b'write = 2

    • 寫入 '1''2'write = 4

    • read 移動到 13,循環結束。

輸出:數組變為 ['a', 'b', '1', '2'],新長度為 4。

八、常見問題解答

Q1:為什么選擇雙指針法?

雙指針法能夠高效地在原地完成數組的壓縮。它通過兩個指針分別負責讀取和寫入操作,避免了使用額外的存儲空間。這種方法在時間復雜度和空間復雜度上都具有顯著優勢,特別適合處理這類原地修改的問題。

Q2:如何處理計數大于 9 的情況?

當計數大于 9 時,將計數轉換為字符串,然后逐個字符寫入數組。例如,計數為 12 時,寫入 '1''2'。這種方法確保了所有計數都能正確表示,無論其大小如何。

Q3:算法是否適用于所有長度的數組?

是的。該算法適用于所有長度的數組,包括空數組、單個字符數組以及包含多個重復字符組的數組。在代碼開頭,我們對空數組進行了特殊處理,返回 0。對于其他情況,算法都能正確處理。

九、總結

字符數組壓縮算法是一個典型的原地操作問題,通過雙指針法能夠在 O(n) 時間復雜度和 O(1) 空間復雜度下完成任務。該算法的核心在于高效地識別連續重復字符組,并將它們轉換為壓縮形式。通過詳細解析和示例分析,我們希望讀者能夠深入理解這一算法的原理和實現細節。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76280.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76280.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76280.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

alertManager部署安裝、告警規則配置詳解及告警消息推送

? java接受告警請求RestController RequestMapping("/alert") Slf4j public class TestApi {private static final DateTimeFormatter FORMATTER DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");RequestMappingpublic void sendTemplate(HttpServl…

數據庫勒索病毒威脅升級:企業數據安全防線如何用安當RDM組件重構

摘要&#xff1a;2025年Q1全球數據庫勒索攻擊量同比激增101.8%&#xff0c;Cl0p、Akira等團伙通過邊緣設備漏洞滲透企業核心系統&#xff0c;制造業、金融業等關鍵領域面臨數據加密與業務停擺雙重危機。本文深度解析勒索病毒對數據庫的五大毀滅性影響&#xff0c;結合安當RDM防…

thanos sidecar和receive區別?

Thanos Sidecar 和 Thanos Receive 是 Thanos 生態系統中兩個關鍵組件&#xff0c;但它們在架構中的作用和功能上有明顯的區別。以下是它們的主要區別&#xff1a; 1. Thanos Sidecar 功能&#xff1a; 與 Prometheus 集成&#xff1a; Sidecar 是一個部署在每個 Prometheus…

Unity入門筆記(緣更)

內容來源SiKi學院的Luna’s Fantasy 文章目錄 一、基礎知識1.準備2.基礎知識1.層級(Layer)2.軸心點3.預制體(Prefab)4.剛體組件(Rigidbody)5.碰撞器組件(BoxCollider) 二、代碼1.移動 一、基礎知識 1.準備 Unity安裝&#xff1a; https://unity.cn 2.基礎知識 1.層級(Layer…

使用VHD虛擬磁盤安裝雙系統,避免磁盤分區

前言 很多時候&#xff0c;我們對現在的操作系統不滿意,就想要自己安裝一個雙系統 但是安裝雙系統又涉及到硬盤分區,非常復雜,容易造成數據問題 虛擬機的話有經常用的不爽,這里其實有一個介于虛擬機和雙系統之間的解決方法,就是使用虛擬硬盤文件安裝系統. 相當于系統在機上…

ARINC818協議(五)

1.R_CTL,設置固定的0x44即可 2.Dest_ID:目的地D_ID,如果不需要目的地址&#xff0c;就設置為0&#xff1b;ADVB協議支持 多個視頻目的地址&#xff0c;廣播通信; 3.cs_ctl在FC-AV上不用 4.source_ID:S_ID [23:0]包含源實體的端口的地址標識&#xff1b;不用就設置為0. ADVB允許…

鴻蒙開發對于RelativeContainer高度設置‘auto‘后還是沒有自適應問題的解決方案

RelativeContainer設置高度為自適應‘auto’沒用生效&#xff0c;查看了官方文檔(文檔中心)也沒用給出明確的答案。只說了不能把錨點設置成父組件錨點&#xff08;__container__&#xff09;。也嘗試了使用guidline來替換父組件錨點&#xff0c;還是沒能自適應高度。 后來嘗試讓…

k8s教程3:Kubernetes應用的部署和管理

學習目標 理解Kubernetes中應用部署的基本概念和方法掌握Deployment、ReplicaSet、StatefulSet、DaemonSet、Job與CronJob等控制器的使用了解Helm作為Kubernetes的包管理工具的基本使用通過實際示例學習應用的部署、更新與管理 Kubernetes提供了一套強大而靈活的機制&#xff…

通過特定協議拉起 electron 應用

在 Android 通過 sheme 協議可以拉起其他應用。 electron 應用也可以通過類似特定協議被拉起。 在同時有 web、客戶端的應用里&#xff0c;可以通過這種方式在 web 拉起客戶端。 支持拉起客戶端 const PROTOCOL xxxif (process.defaultApp) {// 這里是開發環境&#xff0c;有…

算法備案的審核標準是什么?

隨著《互聯網信息服務算法推薦管理規定》等法規的出臺&#xff0c;算法備案成為了強制性備案&#xff0c;是產品合規上線的必要條件之一。本篇內容將從企業視角出發&#xff0c;分析算法備案的常見問題&#xff0c;意在對有備案需求的小伙伴們有所幫助。 一、誰需要做算法備案…

回顧與動機 - 為什么我們需要 Transformer

在接下來的旅程中,我們將一起探索深度學習領域最重要、最具影響力的模型架構之一——Transformer。從它的基本原理出發,逐步深入,最終能夠親手實現一個文本生成模型。 本系列教程假設你已經具備一定的深度學習基礎,了解神經網絡、損失函數、優化器等基本概念,并且熟悉 Py…

探索 Higress:下一代云原生 API 網關

引言 在云原生時代&#xff0c;API 網關作為連接客戶端與后端服務的橋梁&#xff0c;扮演著至關重要的角色。Higress 是一款由阿里巴巴開發的先進云原生 API 網關&#xff0c;基于開源的 Istio 和 Envoy 構建。它通過將流量網關、微服務網關和安全網關三者高度集成&#xff0c…

Spring Boot 整合 DeepSeek 實現AI對話 (保姆及教程)

文章目錄 文章目錄 前言 一、創建 spring boot 工程 二、申請key 三、修改配置文件 application.properties 四、編寫控制器&#xff08;controller&#xff09; 五、運行調試 前言 提示&#xff1a;隨著人工智能的不斷發展&#xff0c;ai這門技術也越來越重要&#xff0c;很多…

前端資源加載失敗后重試加載(CSS,JS等引用資源)

前端資源加載失敗后的重試 .前端引用資源時出現了資源加載失敗(這里針對的是路徑引用異常或者url解析錯誤時) 解決這個問題首先要明確一下幾個步驟 1.什么情況或者什么時候重試 2.如何重試 3.重試過程中的邊界處理 這里引入里三個測試腳本&#xff0c;分別加載里三個不同的腳…

無刷電機槽數相同、轉子極數不同的核心區別

一、基礎原理差異 無刷電機的核心參數: 槽數(定子槽數,記為 ( Z )):定子鐵芯上的繞組槽數量,決定繞組布局。極數(轉子磁極數,記為 ( 2p )):轉子上的永磁體磁極對數(總極數為 ( 2p ),如 ( p=4 ) 表示 8 極)。核心關系:槽極配合(( Z/2p ))決定電機電磁結構,相同…

6.Rust+Axum:打造高效 WebSocket 實時通信聊天室

摘要 本文詳細介紹 RustAxum 在 WebSocket 實時通信開發中的應用&#xff0c;包括雙向通信、狀態管理等&#xff0c;實踐構建聊天室應用。 一、引言 在當今的 Web 應用開發中&#xff0c;實時通信變得越來越重要。WebSocket 作為一種在單個 TCP 連接上進行全雙工通信的協議&…

clickhouse數據導出導入

clickhouse數據導出導入 CSV格式導出為csv格式導入為csv格式 JSON格式導出為json格式導入為json格式 SQL格式導出為SQL CSV格式 導出為csv格式 # 不帶表頭 clickhouse-client -h 127.0.0.1 --database"db" --query"select * from db.test_table FORMAT CSV&qu…

人臉掃描黑科技:多相機人臉掃描設備,打造你的專屬數字分身

隨著科技的迅猛發展&#xff0c;人臉掃描這個詞已經并不陌生&#xff0c;通過人臉掃描設備制作超寫實人臉可以為影視制作打造逼真角色、提升游戲沉浸感&#xff0c;還能助力教育機構等領域生產數字人以豐富教學資源&#xff0c;還在安防、身份識別等領域發揮關鍵作用&#xff0…

學習型組織與系統思考

真正的學習型組織不是只關注個人的學習&#xff0c;而是關注整個系統的學習。—彼得圣吉 在這兩年里&#xff0c;越來越多的企業開始詢問是否可以將系統思考的內容內化給自己的內訓師&#xff0c;進而在公司內部進行教學。我非常理解企業這樣做的動機&#xff0c;畢竟內部講師…

gl-matrix 庫簡介

gl-matrix 庫簡介 gl-matrix 是一個高性能的 JavaScript 矩陣和向量庫&#xff0c;專門為 WebGL 和其他 3D 圖形應用設計。它提供了處理 2D、3D 和 4D 向量以及矩陣運算的高效方法。 主要特性 高性能&#xff1a;經過高度優化&#xff0c;執行速度快輕量級&#xff1a;體積小…