LeetCode 3. Longest Substring Without Repeating Characters(用動態規劃)

題目

網站題目鏈接
題目簡述:給出字符串s,找出s中最長的不存在重複字符的子串的長度

給出 "abcabcbb", 答案子串是 "abc", 返回長度 3
給出 "bbbbb"   , 答案子串是 "b"  , 返回長度 1
給出 "pwwkew"  , 答案子串是 "wke", 返回長度 3

思路

  1. 區分子串和子序列
    例如原始串s : abcabcbb
    子序列: abbbb 、cbcb、abc 等均按原始串中字符順序選取部分字符組成,但字符之間不必相鄰
    子串:abc 、cabcb等均爲連續的子序列
    即子串是子序列的真子集

  2. 題目說的字符沒指明單純是字母,因此需要考慮全部128個ASCII碼

  3. 動態規劃
    dp[i] :以s[i]結尾的符合要求(最長的不存在重複字符)的子串長度
    當 i = 0,dp[i] = 1
    當 i ≥ 1,dp[i] = min( dp[i - 1] + 1,loc(s[i]) - pre_loc(s[i]) )

    其中 loc(s[i]) - pre_loc(s[i]) : 當前字符s[i]的位置到該字符前一次出現的位置的距離
    例如,
    遍歷abcabcbb,
    當i = 2時,s[i] 爲 c,那麼 loc(s[i]) - pre_loc(s[i]) = 2 - (-1) = 3,pre_loc=-1表示之前沒出現過
    當i = 4時,s[i] 爲 b,那麼 loc(s[i]) - pre_loc(s[i]) = 4 - 1 = 3

  4. 生成記錄表用於計算 loc(char) - pre_loc(char)
    二維空間vector<vector<int>> ascii_loc_list(ascii_size)記錄每種字符在字符串中對應的所有下標
    每行記錄着一種字符在字符串中出現的座標(按序從左到右)
    例如,
    對於abcabcbb,
    ascii_loc_list[98] = {1,4,6,7} 記錄着字符‘b’在字符串中出現的所有座標,‘b’的ASCII碼是98

代碼

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

class Solution {
public:
    // 根據當前字符x處於字符串s中的座標curr_loc,從字符x的列表locs中,找出前一次出現的座標pre_loc
    int find_pre_loc(vector<int> locs, int curr_loc) {

        int index = 0;
        for (index = 0; index < locs.size(); index++) {
            if (locs[index] == curr_loc) break;
        }

        // 如果是當前是第一次出現則返回 -1 表示之前沒出現過
        return (index - 1 < 0) ? -1 : locs[index - 1];
    }

    int lengthOfLongestSubstring(string s) {

        int ascii_size = 128, str_size = s.length();

        // 初始化記錄列表,每行記錄字符 x 在字符串 s 中出現的位置下標(從左到右)
        vector<vector<int> > ascii_loc_list(ascii_size);
        for (int loc = 0; loc < str_size; loc++) {
            int ch = (int)s[loc];
            ascii_loc_list[ch].push_back(loc);
        }

        //左到右掃描一次,loc[i]表示以s[i]結尾的最長不包含重複字符的子串長度
        int* dp = new int[str_size];
        int max_len = 0;
        for (int loc = 0; loc < str_size; loc++) {
            int ch = (int)s[loc];
            int pre_loc = find_pre_loc(ascii_loc_list[ch], loc);

            //臨界:以第一個字母結束的串長度肯定爲1
            if (loc == 0) max_len = dp[loc] = 1;
            else {
                dp[loc] = min(dp[loc - 1] + 1, loc - pre_loc);
                max_len = max(max_len, dp[loc]);
            }
        }

        return max_len;
    }
};

int main() {

    Solution s;

    cout << s.lengthOfLongestSubstring("abcabcbb") << endl; // abc ,3
    cout << s.lengthOfLongestSubstring("bbbbb") << endl;    // b   ,1
    cout << s.lengthOfLongestSubstring("pwwkew") << endl;   // wke ,3
    cout << s.lengthOfLongestSubstring("c") << endl;        // c   ,1


     /**
      * 提交後發現過不了全部樣例,才發現題目說的字符不止是26個字母,要包括所有ASCII碼!!!
      * 下面是一個測試樣例的一部分..沒錯只是一部分,太長了放不下我刪了中間很多...
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
         56789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopq
         rstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+
         ,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzABCDEFGH
         56789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopq
         rstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+
         ,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzABCDEFGH
         IJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_
         `{|}~ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY
         Z0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijk
         lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%
         &'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzAB
         CDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@
         [\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS
         TUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcde
         fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
         !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuv
         wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:
         ;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM
         NOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~
         abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
         56789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopq
         rstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+
         ,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzABCDEFGH
         IJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_
         Z0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijk
         lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%
         &'()*+,-./:;<=>?@[\\]^_`{|}~ abcdefghijklmnopqrstuvwxyzAB"
      */

    int wait;
    cin >> wait;
    return 0;
}
發佈了58 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章