同窗去面抖音被問到了這道題,趕忙去看了一下 發現本身也不會
哈哈哈哈哈,so.. 記個筆記 便於複習數組
題目描述code
找到給定字符串(由小寫字符組成)中的最長子串 T , 要求 T 中的每一字符出現次數都很多於 k 。 輸出 T 的長度。示例 1:字符串
輸入: s = "aaabb", k = 3 輸出: 3 最長子串爲 "aaa" ,其中 'a' 重複了 3 次。示例 2:string
輸入: s = "ababbc", k = 2 輸出: 5 最長子串爲 "ababb" ,其中 'a' 重複了 2 次, 'b' 重複了 3 次。
這道題的意思就是找一個子串,這個子串裏的全部字符的出現頻率都不低於K,找出最長的這樣的子串
還有題目沒有說太明確,其實由小寫字符組成就是說只有‘a-z‘的小寫字母,這樣咱們就能夠方便地用數組來統計啦~io
思路:
若是不知足條件的字符出如今了字符串兩邊好說,咱們只須要把兩邊不知足條件的字符去掉
麻煩的是 字符可能出如今中間 因而考慮用分治法去解決這個問題 把大問題劃分爲幾個小問題, 若是字符出如今了中間 咱們就把字符串從這個字符這裏劈開,左邊去求解這個問題,右邊也去求解這個問題,最後取左右倆邊結果的最大值就OK了
關於某個字符是否知足條件,咱們只須要提早遍歷一遍字符串,統計一下就OK了~class
代碼以下:遍歷
class Solution { public int longestSubstring(String s, int k) { if(s==null) return 0; if(s.length()==0) return 0; if(k<=1) return s.length(); return count(s, k, 0, s.length()-1); } public int count(String s, int k, int left , int right){ if(right-left+1<k) return 0; int[] cnt = new int[26]; for(int i=left;i<=right;i++){ ++cnt[s.charAt(i)-'a']; } // 去除左右兩邊不知足條件的字符 while(right-left+1>=k && cnt[s.charAt(left)-'a']<k){ left++; } while(right-left+1>=k && cnt[s.charAt(right)-'a']<k){ right--; } if(right-left+1<k) return 0; // 劈開分治 for(int i =left;i<=right;i++){ // 只須要劈開一次就能夠返回了, // 由於即便右邊還有不知足條件的字符, // 也會在其子階段求解獲得了 if(cnt[s.charAt(i)-'a']<k){ return Math.max(count(s, k, left, i-1), count(s, k, i+1, right)); } } return right-left+1; } }