<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          每日一道 LeetCode (48):最長回文子串

          共 622字,需瀏覽 2分鐘

           ·

          2020-09-17 15:42

          ?

          每天 3 分鐘,走上算法的逆襲之路。

          ?

          前文合集

          每日一道 LeetCode 前文合集

          代碼倉庫

          GitHub:https://github.com/meteor1993/LeetCode

          Gitee:https://gitee.com/inwsy/LeetCode

          題目:最長回文子串

          難度:「中等」

          題目來源:https://leetcode-cn.com/problems/longest-palindromic-substring/

          給定一個字符串 s,找到 s 中最長的回文子串。你可以假設(shè) s 的最大長度為 1000。

          示例 1:

          輸入:?"babad"
          輸出:?"bab"
          注意:?"aba"?也是一個有效答案。

          示例 2:

          輸入:?"cbbd"
          輸出:?"bb"

          解題方案一:暴力解法

          暴力方案就很適合我這種腦子不夠用的人,首先把字符串中的所有子串取出來,當(dāng)然哈,取長度大于 1 的子串,不然也沒啥意義。

          然后挨個判斷取出來的子串是否回文串,判斷完了以后取到最大的那個,然后返回出來,結(jié)束。

          public?String?longestPalindrome(String?s)?{
          ????int?len?=?s.length();
          ????if?(len?2)?{
          ????????return?s;
          ????}
          ????//?先把字符串轉(zhuǎn)成數(shù)組
          ????char[]?charArray?=?s.toCharArray();
          ????//?定義初始位置
          ????int?left?=?0;
          ????//?定義字符串長度
          ????int?length?=?1;
          ????//?獲取所有子串
          ????for?(int?i?=?0;?i?1;?i++)?{
          ????????for?(int?j?=?i?+?1;?j?????????????if?(j?-?i?+?1?>?length?&&?valid(charArray,?i,?j))?{
          ????????????????left?=?i;
          ????????????????length?=?j?-?i?+?1;
          ????????????}
          ????????}
          ????}
          ????return?s.substring(left,?left?+?length);
          }

          //?判斷是否回文串
          private?boolean?valid(char[]?charArray,?int?left,?int?right)?{
          ????while?(left?????????if?(charArray[left]?!=?charArray[right])?{
          ????????????return?false;
          ????????}
          ????????left++;
          ????????right--;
          ????}
          ????return?true;
          }

          這個答案慢肯定是慢,時間復(fù)雜度達(dá)到了 O(n^3) ,不慢才有鬼了。

          解題方案二:中心擴散

          上面的方案是從兩邊開始往中間夾,中心擴散的思想是從中間開始往兩邊進(jìn)行擴散。

          我在答案中找到了一個非常形象的圖解,和大家分享一下:

          解釋一下這張圖,現(xiàn)在假設(shè)有一個字符串 「acdbbdaa」 ,從第一個 b 位置開始找最長回文串。

          • 首先往左尋找與當(dāng)期位置相同的字符,直到遇到不相等為止。
          • 然后往右尋找與當(dāng)期位置相同的字符,直到遇到不相等為止。
          • 最后左右雙向擴散,直到左和右不相等。

          這時我們找到了從 b 開始最長的回文子串,然后在程序中記錄下來。

          每一個位置開始都按這個方案去找最長的回文子串,最后得到的結(jié)果就是最長的回文子串。

          public?String?longestPalindrome_1(String?s)?{
          ????if?(s?==?null?||?s.length()?==?0)?return?"";

          ????int?length?=?s.length();
          ????//?定義左右指針
          ????int?left?=?0,?right?=?0;
          ????//?定義長度
          ????int?len?=?1;
          ????//?定義最大開始位置和最長子串長度
          ????int?maxStart?=?0,?maxLen?=?0;
          ????for?(int?i?=?0;?i?????????left?=?i?-?1;
          ????????right?=?i?+?1;
          ????????//?計算左邊
          ????????while?(left?>=?0?&&?s.charAt(left)?==?s.charAt(i))?{
          ????????????len++;
          ????????????left--;
          ????????}
          ????????//?計算右邊
          ????????while?(right?????????????len++;
          ????????????right++;
          ????????}
          ????????//?兩邊一起擴散
          ????????while?(left?>=?0?&&?right?????????????len?+=?2;
          ????????????left--;
          ????????????right++;
          ????????}
          ????????//?如果當(dāng)前長度大于最大長度
          ????????if?(len?>?maxLen)?{
          ????????????maxLen?=?len;
          ????????????maxStart?=?left;
          ????????}
          ????????//?下次循環(huán)前重置?len
          ????????len?=?1;
          ????}
          ????return?s.substring(maxStart?+?1,?maxStart?+?1?+?maxLen);
          }

          解題方案三:動態(tài)規(guī)劃

          動態(tài)規(guī)劃我的理解實際上就是一個把已經(jīng)判斷過的信息緩存起來的一種方案,很像我們在做 Web 開發(fā)的時候用到的 redis ,只是在答案中換成了一個矩陣或者說是二維數(shù)組。

          如果一個字符串 s[l, r] 是一個回文串,那么 s[l + 1, r - 1] 一定也是一個回文串,相當(dāng)于兩頭各去掉一個字符。

          如果這時我們直接通過某種方式直接可以知道 s[l + 1, r - 1] 是一個回文串,那么只需要判斷 s[i] 和 s[j] 相等就可以了。

          所以就有了下面的代碼:

          public?String?longestPalindrome_2(String?s)?{
          ????if?(s?==?null?||?s.length()?==?0)?return?s;
          ????int?length?=?s.length();
          ????int?maxStart?=?0;??//最長回文串的起點
          ????int?maxEnd?=?0;????//最長回文串的終點
          ????int?maxLen?=?1;??//最長回文串的長度

          ????//?定義一個布爾矩陣
          ????boolean[][]?dp?=?new?boolean[length][length];
          ????for?(int?r?=?1;?r?????????for?(int?l?=?0;?l?????????????if?(s.charAt(r)?==?s.charAt(l)?&&?(r?-?l?<=?2?||?dp[l?+?1][r?-?1]?==?true))?{
          ????????????????dp[l][r]?=?true;
          ????????????????if?(r?-?l?+?1?>?maxLen)?{
          ????????????????????maxLen?=?r?-?l?+?1;
          ????????????????????maxStart?=?l;
          ????????????????????maxEnd?=?r;
          ????????????????}
          ????????????}
          ????????}
          ????}
          ????return?s.substring(maxStart,?maxEnd?+?1);
          }

          可以看到耗時也是蠻多的。

          答案中還給出了一種叫做 Manacher 算法的方案,原諒我比較菜,屬實是沒看懂,就不拿出來獻(xiàn)丑了。





          感謝閱讀



          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  高清一区二区三区 | 黄色在线观看有限公司jb啊啊相当到位 | 性爱視频一区二区三区 | 色婷婷视频网站 | 日韩A级 日韩抽插 |