[LeetCode] #3 Longest Substring Without Repeating Characters 解題

題目連結

題型解說

這是一題難度為普通的題目

需要設計一個方法,此方法會傳入一個字串 s

要求是找出字串內連續且不重複的字元的長度

abcabcbb => abc => 3
pwwkew => wke => 3

解題思路

創建一個 List ,並走訪一遍字串

遇到 List 沒有的字元就加入

遇到重複的字元就比較當下最大長度與前面最大長度

並且把重複字元前的所有字元移除

程式碼

Java

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s == null) {
            return 0;
        }
        
        if (s.length() < 2) {
            return 1;
        }
        
        int max = 0;
        
        List<Character> list = new ArrayList<>();
        
        for (char c: s.toCharArray()) {
            int index = list.indexOf(c);
            
            if (index > -1) {
                int size = list.size();
                
                max = Math.max(size, max);
                
                for (int i = 0; i <= index; i++) {
                    list.remove(0);
                }
            }
            
            list.add(c);
        }
        
        return Math.max(list.size(), max);
    }
}

更好的解法

上面是我沒參考答案自己弄出來的一種方式

後來研究其他人提供的解法,找到了更簡略的方式

原本的解法1是利用 List 來幫忙紀錄順序

解法2是創建一個長度256的陣列,預設值為-1

一樣走訪字串,並把字元對應的陣列填入該字元的索引值

相等於 List 的 index,並隨時計算左邊界的位置和最大長度

這麼說可能有點模糊,下面我用圖解的方式來說明

01

有兩個變數 max 表示最大長度、left 表示左邊界

文字上面的數字表示出現的位置,-1 代表尚未出現

02

第一個字元

第一步計算左邊界,因為尚未出現重複字元p,故維持 -1

第二步標上位置,p為0

第三步,計算最大值,計算方式為 目前索引 減去 左邊界

0 - (-1) = 1

1 比 0 大,故將 max 改為 1

03

第二個字元

第一步計算左邊界,因為尚未出現重複字元w,故維持 -1

第二步標上位置,w為1

第三步,計算最大值,計算方式為 目前索引 減去 左邊界

1 - (-1) = 2

2 比 1 大,故將 max 改為 2

04

第三個字元

第一步計算左邊界,因為出現重複字元w,故將左邊界改為上一個重複字元的位置 1

第二步標上位置,w為2

第三步,計算最大值,計算方式為 目前索引 減去 左邊界

2 - 1 = 1

1 比 2 小,故 max 維持 2

05

第四個字元

第一步計算左邊界,因為尚未出現重複字元k,故維持 1

第二步標上位置,k為3

第三步,計算最大值,計算方式為 目前索引 減去 左邊界

3 - 1 = 2

2 和 2 一樣大,故 max 維持 2

06

第五個字元

第一步計算左邊界,因為尚未出現重複字元e,故維持 1

第二步標上位置,e為4

第三步,計算最大值,計算方式為 目前索引 減去 左邊界

4 - 1 = 3

3 比 2 大,故將 max 改為 3

07

第六個字元

第一步計算左邊界,因為出現重複字元w,故將左邊界改為上一個重複字元的位置 2

第二步標上位置,w為5

第三步,計算最大值,計算方式為 目前索引 減去 左邊界

5 - 2 = 3

3 和 3 一樣大,故 max 維持 3

最終回傳值為 3,若是需要回傳字串本身,答案是 wke 或是 kew 兩種

程式碼

Java

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s == null) {
            return 0;
        }
        
        if (s.length() < 2) {
            return s.length();
        }
        
        int[] temp = new int[256];
        
        Arrays.fill(temp, -1);
        
        int max = 0;
        int left = -1;
        
        for (int i = 0, len = s.length(); i < len; ++i) {
            left = Math.max(left, temp[s.charAt(i)]);
            
            temp[s.charAt(i)] = i;
            
            max = Math.max(max, i - left);
        }
        
        return max;
    }
}

Read more

[LeetCode] #12 Integer to Roman 解題

題目連結 題型解說 這是一題難度為普通的題目 需要設計一個方法,此方法會傳入一個整數 num 要求是把整數轉換成羅馬字母,轉換清單如下 I => 1 V => 5 X => 10 L => 50 C => 100 D => 500 M => 1000 但羅馬字母有一些特殊規則 4 並非 IIII 而是 IV,9 並非 VIIII 而是 IX 這規則同樣可以套用到 40 90 400 900 解題思路 既然知道特殊規則是一樣的,變得是使用的符號,那麼先從 num 取個位數開始 轉換完成後,把 num 除上 10,消除個位數,

By Michael

[LeetCode] #11 Container With Most Water 解題

題目連結 題型解說 這是一題難度為中等的題目 需要設計一個方法,此方法會傳入一個數字陣列 height 陣列中的元素代表每一個柱子的高度 現在需要計算出,該陣列中以某兩隻柱子為邊界,最多可以裝多少水 以範例來說 height = [1,8,6,2,5,4,8,3,7] 最多可以裝 7 * 7 = 49 單位的水 解題思路 計算面積就是底乘上高 底的計算方式為 「右邊柱子的 index」 減去 「左邊柱子的 index」 高就取最短的那一根柱子高度 拿題目給的例子來當範例 建立三個變數 result、left、right left、right 代表左右兩邊的 index result 代表目前最大容量,初始值 0 第一步,找出最短的柱子高度,

By Michael

[LeetCode] #941 Valid Mountain Array 解題

題目連結 題型解說 這是一題難度為簡單的題目 需要設計一個方法,此方法會傳入一個數字陣列 arr 判斷陣列中的元素是不是由低到高再從高到低(山形)的排序,且不連續一個以上數字 比如說 [1,2,3,2] 就是一個山形陣列,但 [1,2,2,3,2] 不是,因為有兩個 2 [1,2,3,4,5] 和 [5,4,3,2,1] 也不算是山形陣列,前者只有往上沒有往下,後者相反 解題思路 準備一個數字變數(temp)和布林變數(asc),跑一次迴圈,有可能遇到如下狀況 1. 某個數字與前一個數字相同,這時候直接回傳 false

By Michael

[LeetCode] #944 Delete Columns to Make Sorted 解題

題目連結 題型解說 這是一題難度為簡單的題目 需要設計一個方法,此方法會傳入一個字串陣列 strs 這個陣列中每個字串的長度都相同,字串內容都是小寫英文 需要檢查每個元素的第 N 個字元是不是由小至大排列,並回傳有幾個錯誤排列 比如傳入的陣列長這樣 ["cba","daf","ghi"] 取第一個字元 = cdg 取第二個字元 = bah 取第三個字元 = afi 其中第二組的結果(bah)並不是由小至大排列,故回傳 1 解題思路 這一題就用兩個迴圈各別把字元取出來,並比較是否比上一個字元大(Java 中的字元可以直接比較),如果不是就將結果+1 程式碼 Java class Solution { public int minDeletionSize(String[] strs) { int result = 0; for (int i = 0,

By Michael