LeetCode-3 無重複字符的最長子串

 

LeetCode-3 無重複字符的最長子串

 

  • 題目:3. 無重複字符的最長子串
  • 難度:中等
  • 分類:字符串
  • 解決方案:雙指針、滑動窗口

<!-- more -->

LeetCode前幾道題都是經典題,今天我們學習第3題無重複字符的最長子串,這道題在秋招面試中遇見過,再次相遇,如此親切。下面我們看看這道題的題目描述。

題目描述

給定一個字符串,請你找出其中不含有重複字符的最長子串的長度。
示例1:

1

2

3

輸入: "abcabcbb"

輸出: 3

解釋: 因爲無重複字符的最長子串是 "abc",所以其長度爲 3

示例2:

1

2

3

輸入: "bbbbb"

輸出: 1

解釋: 因爲無重複字符的最長子串是 "b",所以其長度爲 1

示例3:

1

2

3

4

輸入: "pwwkew"

輸出: 3

解釋: 因爲無重複字符的最長子串是 "wke",所以其長度爲 3

     請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串。

分析

首先我們看看這個題的示例3,該示例中提示我們這個題需要求的字符串的子串而不是子序列,我們具體來看看什麼是子串,什麼是子序列。

子串:字符串中任意個連續的字符組成的子序列稱爲該串的子串。注意子串強調字符的連續性。
圖片說明
子序列:字符串中去掉任意個元素後得到的結果即爲該字符串的子序列。注意子序列中字符出現的次序與原字符串中字符出現的次序要保持一致。
圖片說明

區分子串和子序列後,我們再回過頭來看看這個題。我們先動手畫一畫示例1的解題過程,如下圖所示:
圖片說明
從上圖我們可以觀察出,可以使用雙指針(left指針和right指針)來維護一個滑動窗口,這個窗口內的字符都是沒有重複的,遍歷一趟字符串後就可以得到最大的子串,因此時間複雜度爲O(n)。現在想一個問題:right指針指向的字符怎麼確定它在前面是否出現過,若出現過,它出現的位置在哪兒?對於這個問題,做過LeetCode-1 兩數之和這道題的小夥伴們應該知道,我們可以使用HashMap記錄一個字符是否出現以及出現後的位置。對於重複多次出現的字符,我們是保留所有出現的位置還是隻記錄一個位置?觀察示例1分析過程可以知道,我們只需要保存一個最大位置即可。還有一個關鍵點,我們如何確定left指針的位置?這一點非常重要,需要分情況討論。

  • 當目前right指針指向的字符未出現過,left指針不需要移動;
  • 當目前right指針指向的字符出現過,如果該字符在窗口中,即該字符出現在當前left指針的右邊,則通過HashMap獲取字符的位置並向右移動一位即爲更新後left的位置;如果該字符在窗口外面,即在當前left指針的左邊,則不需要移動left的位置。
    分析完後,再看看java代碼的具體實現:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    class Solution {

      public int lengthOfLongestSubstring(String s) {

          int res = 0;

          if(s.length() == 0)

              return res;

          // 創建HashMap,用來保存字符與位置之間的對應關係

          HashMap<Character, Integer> hashMap = new HashMap<>();

          // 初始化左指針和右指針,並遍歷字符串

          for(int left = 0, right = 0; right < s.length(); right++){

              // 判斷右指針指向的字符是否出現過

              if(hashMap.containsKey(s.charAt(right))){

                  // 確定左指針的位置

                  left = Math.max(left, hashMap.get(s.charAt(right))+1);

              }

              // 對於第一次出現的字符,保存該字符的位置;對於多次出現的字符,更新該字符出現的位置

              hashMap.put(s.charAt(right), right);

              // 更新窗口的大小,保存最大的窗口大小

              res = Math.max(res, right-left+1);

          }

          return res;

      }

    }

    圖片說明
    整個算法流程的時間複雜度爲O(n),空間複雜度爲O(1)

Github地址

LeetCode-3 無重複字符的最長子串

參考鏈接

發佈了111 篇原創文章 · 獲贊 79 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章