快轉到主要內容
leetcode 1062 - Longest Repeating Substring

leetcode 1062 - Longest Repeating Substring

·
類別 
Leetcode
標籤 
Java Leetcode Medium Binary Search Problem
Eason Chiu
作者
Eason Chiu
一個不做筆記就容易忘記的工程師
目錄

題目
#

leetcode 1062 - Longest Repeating Substring(題目說明請點連結)

題目簡述
#

給定一個字串,找到最長的重複子字串的長度。重複子字串是指在字串中出現至少兩次的子字串。

Example 1:

Input: "abcd"
Output: 0
Explanation: 沒有重複的子字串。

Example 2:

Input: "abbaba"
Output: 2
Explanation: 最長的重複子字串是 "ab" 和 "ba",每個都出現兩次。

Example 3:

Input: "aabcaabdaab"
Output: 3
Explanation: 最長的重複子字串是 "aab",出現了 3 次。

Example 4:

Input: "aaaaa"
Output: 4
Explanation: 最長的重複子字串是 "aaaa",出現了兩次。

解題思路
#

輸入為一個字串,輸出為字串內重複最多的子字串的次數。
這題的思路可以利用有序區間和單調性特性:
假設輸入字符串為 S = “aabcaabdaab”,我們嘗試檢查不同的子串長度是否有重複。

  • 子串長度和重複性: 子串長度 𝐿 (aabcaabdaab)

    L是否有重複子串重複部分
    1單字符如 “a” 重複多次
    2如 “aa” 或 “ab” 重複
    3如 “aab” 重複
    4沒有重複長度 4 的子串
    5沒有重複長度 5 的子串
    6沒有重複長度 6 的子串
  • 有序區間:從 1 到 6(子串長度)是有序的,因為是否有重複子串隨著長度變化而遵守規律。

  • 單調性:
    當 𝐿≤3 時,存在重複子串。
    當 L≥4 時,不存在重複子串。



透過 Binary search 在這個有序陣列當中找到最大重複的那個數字,
並寫另外寫一個方法用HashSet來判斷是否有重複值。

例子說明
#

s = "aabcaabdaab"

  • 初始情況:left = 1right = 11
  1. 第一次二分:mid = 6

    • 檢查長度 6 的子串是否有重複
    • 沒有重複,right = mid - 1 = 5
  2. 第二次二分:mid = 3

    • 檢查長度 3 的子串是否有重複
    • “aab” 重複 3 次,有重複,left = mid = 3
  3. 第三次二分:mid = 4

    • 檢查長度 4 的子串是否有重複
    • 沒有重複,right = mid - 1 = 3
  4. 最終結果:

    • left = 3,返回 3

完整程式碼
#

java
class Solution {
    public int longestRepeatingSubstring(String s) {
        int left = 1, right = s.length(); // 初始化二分搜索的範圍

        while(left < right) { // 當left小於right時繼續搜索
            int mid = left + (right - left + 1) / 2; // 計算中間值,使用上取整
            if(hasRepeatingSubstring(s, mid)) { // 檢查是否有長度為mid的重複子串
                left = mid; // 如果有重複,嘗試更大的長度
            } else {
                right = mid - 1; // 如果沒有重複,嘗試更小的長度
            }
        }

        return left; // 返回最長重複子串的長度
    }
    
    public boolean hasRepeatingSubstring(String s, int length) {
        HashSet<String> set = new HashSet<>(); // 創建HashSet來存儲子串

        for (int i = 0; i <= s.length() - length; i++) { // 遍歷所有可能的起始位置
            if(set.contains(s.substring(i, i + length))) { // 檢查當前子串是否已經存在
                return true; // 如果存在,說明有重複
            } else {
                set.add(s.substring(i, i + length)); // 將當前子串加入集合
            }
        }

        return false; // 沒有找到重複子串
    }
}

時間複雜度
#

  • 時間複雜度:O(n² log n),其中 n 是字串的長度。

    • 最佳情況:若字串中很快就找到重複子串,則每次二分時 hasRepeatingSubstring 很快返回,實際遍歷的子串較少,接近 O(n log n)。
    • 最差情況:每次都要完整檢查所有長度為 mid 的子串,且二分 log n 次,每次檢查 O(n) 個子串,每個子串長度 O(n),所以總體為 O(n² log n)。
  • 空間複雜度:O(n²),用於存儲所有可能的子串於 HashSet 中。

相關文章

leetcode 15 - 3Sum
類別 
Leetcode
標籤 
Java Leetcode Medium Two Pointers Problem Blind75
leetcode 11 - Container With Most Water
類別 
Leetcode
標籤 
Java Leetcode Medium Two Pointers Problem Blind75
leetcode 80 - Remove Duplicates from Sorted Array II
類別 
Leetcode
標籤 
Java Leetcode Medium Two Pointers Problem