1. 程式人生 > 其它 >Leetcode題目總結[3]無重複字元的最長字串

Leetcode題目總結[3]無重複字元的最長字串

1.題目描述

給定一個字串s,請你找出其中不含有重複字元的最長子串的長度。

示例1:

輸入: s = "abcabcbb"
輸出: 3 
解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。

示例 2:

輸入: s = "bbbbb"
輸出: 1
解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。

示例 3:

輸入: s = "pwwkew"
輸出: 3
解釋: 因為無重複字元的最長子串是"wke",所以其長度為 3。
    請注意,你的答案必須是 子串 的長度,"pwke"是一個子序列,不是子串。

示例 4:

輸入: s = ""
輸出: 0

提示:

  • 0 <= s.length <= 5 * 104
  • s由英文字母、數字、符號和空格組成

2.做法

首先要分清楚子串和子序列

子串:串中任意個連續的字元組成的子序列稱為該串的子串 如:coffee中的offe是一個子串

序列:序列是被排成一列的物件(或事件);這樣每個元素不是在其他元素之前,就是在其他元素之後。這裡,元素之間的順序非常重要

子序列:子序列就是在原來序列中找出一部分組成的序列 如:coffee中的ofe可以是一個子序列,而不可以是一個子串

一開始啥想法都沒有,瞄了一眼題解,滑動視窗+hashmap?

看了一會迷迷糊糊地也沒怎麼看懂 但是到自己真動手寫的時候就知道為什麼是滑動視窗+hashmap了

最暴力的做法就是枚舉出所有區間並判斷區間內是否有重複字元 並找出符合條件的最長區間

一共有Σ? 好吧算不出來總之就是很多個不合法區間

我們可以利用兩個指標組成一個滑動視窗,從左往右移動視窗,每次右指標右移一位,加入一個字元,並判斷現在的字串裡有沒有與新字元相同的字元,如果有,則加入這個新字元以後的子串不合法。

我們可以記錄一下沒加入新字元時的字串長度,

然後將左指標右移繼續計算下面的字串

當所有的可能的合法區間都列舉並計算一遍後即可得到答案

判斷:這裡我是直接迴圈區間挨個字元判斷,不知道有沒有其他做法 比如利用hash表中存的字元出現的最後位置與指標位置比較直接判斷之類的?(臨時想法也沒有試過也許有點得不償失?)

左指標右移:一開始我以為只是單純右移一位就可以了(只考慮了樣例1的情況),但是右移之後遇到同樣的字元會出問題(卡了樣例3) 記錄完pw子串的長度後 這個p就沒有用了 因為以這個p開頭的子串最長只能到這裡,所以我們可以在記錄完子串長度後就將這個p廢棄掉, pw中的w也是,假如你說兩個重複w直接可能還有其它合法字元,但是在遇到第二個w之後,以第一個w開頭的子串最長也就到第二個子串為止,而以第一個w後面的字元開頭的子串可能還會更長,所以我們可以捨棄掉第一個w,可以直接將左指標跳到第一個w+1的位置。於是我們用hash記錄每個字元對應的最後出現的位置,在左指標右移時直接移動到對應位置+1就可以了。c++我用的不熟,就用陣列暫時代替了

3.程式碼

C++:

 1 /*
 2  * @lc app=leetcode.cn id=3 lang=cpp
 3  *
 4  * [3] 無重複字元的最長子串
 5  */
 6 
 7 // @lc code=start
 8 class Solution {
 9 public:
10     int lengthOfLongestSubstring(string s) {
11         int len = s.length();
12         int maxans = 0;
13         int start = 0,flag = 0;
14         int temp;
15         int a[500]= {};
16         if(len == 0) return 0;
17         for(int i = 0; i < len; i++)
18         {
19             
20             for(int j = start; j < i; j++)
21             {
22                 if(s[j] == s[i])
23                 {
24                     flag = 1;
25                     temp = a[s[i] - ' '] + 1;
26                     break;
27                 }
28             }
29             if(flag == 1)
30             {
31                 start = temp;
32             }
33             maxans = max(maxans,i - start + 1);
34             flag = 0;
35             a[s[i] - ' '] = i; 
36         }
37         return maxans;
38     }
39 };
40 // @lc code=end

4.做題時遇到的錯誤

runtime error: index -65 out of bounds for type ‘int [26]’

錯誤原因是陣列越界

因為題目沒有限制字元一定是26個英文字母,也可能有'-' ' ' '?' '!' '*'等符號

在建立hash表的時候要將表的範圍擴大一點

我將表的範圍擴到了500就可以了 (隨便選的數字)