<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刷題實(shí)戰(zhàn)87: 擾亂字符串

          共 3065字,需瀏覽 7分鐘

           ·

          2020-11-07 02:17

          算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識(shí)和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個(gè)公眾號(hào)后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !

          今天和大家聊的問題叫做?擾亂字符串,我們先來看題面:

          https://leetcode-cn.com/problems/scramble-string/

          We can scramble a string s to get a string t using the following algorithm:

          If the length of the string is 1, stop.

          If the length of the string is > 1, do the following:

          Split the string into two non-empty substrings at a random index, i.e., if the string is s, divide it to x and y where s = x + y.

          Randomly decide to swap the two substrings or to keep them in the same order. i.e., after this step, s may become s = x + y or s = y + x.

          Apply step 1 recursively on each of the two substrings x and y.

          Given two strings s1 and s2 of the same length, return true if s2 is a scrambled string of s1, otherwise, return false.

          題意


          給定一個(gè)字符串 s1,我們可以把它遞歸地分割成兩個(gè)非空子字符串,從而將其表示為二叉樹。


          樣例


          示例?1:

          輸入: s1 = "great", s2 = "rgeat"
          輸出: true

          示例?2:

          輸入: s1 = "abcde", s2 = "caebd"
          輸出: false


          解題

          https://www.cnblogs.com/techflow/p/13416462.html

          題解

          不知道大家看完題意是什么感覺,是否覺得有些棘手呢?
          棘手歸棘手,但題目的要求還是很明確的。還是老規(guī)矩,我們一點(diǎn)點(diǎn)來分析問題。首先,那個(gè)花里胡哨的爬取操作是一個(gè)可逆操作,也就是說如果字符串s1能夠通過這些操作變成s2,那么同樣s2也可以通過同樣的操作變回s1。從更高的層面來說,它們其實(shí)是一樣的,是同一個(gè)存在的兩個(gè)狀態(tài)。
          進(jìn)一步,如果大家學(xué)過圖論相關(guān)的算法,對(duì)這塊有所了解的話,那么這個(gè)問題還可以進(jìn)一步變形。
          假設(shè)我們最初的字符串是s,它通過一步爬取操作可以變成s1,s2和s3。那么我們可以把這些字符串都抽象成一張無向圖當(dāng)中的節(jié)點(diǎn)。可以看成是s和s1,s2和s3之間有一條邊相連。所以字符串之間能否通過爬取轉(zhuǎn)化的關(guān)系就變成了在圖上是否聯(lián)通的關(guān)系,這個(gè)問題也就變成了在一張無向圖當(dāng)中已知兩點(diǎn),請(qǐng)問這兩點(diǎn)是否聯(lián)通。這個(gè)問題就簡單多了,我們遍歷整張圖就好了。
          縮小到了圖上遍歷之后,整個(gè)問題其實(shí)已經(jīng)出來了,遍歷圖無非兩種方法,一種是深度優(yōu)先搜索,一種是寬度優(yōu)先搜索。這兩種都是老掉牙的算法了,實(shí)在沒什么稀奇的。在這題當(dāng)中深搜寬搜都差不多,看你的喜好了。我個(gè)人是選擇的深搜實(shí)現(xiàn)的。
          對(duì)于字符串的爬取操作而言,一共有兩種可能,一種是s1拆分之后的兩個(gè)部分分別和s2同樣位置的兩個(gè)部分的字符串進(jìn)行比較。還有一種可能是s1的前半部分和s2的后半部分,s1的后半部分和s2的前半部分判斷。這兩種情況其實(shí)是同一個(gè)節(jié)點(diǎn)在搜索樹上的兩個(gè)支路,相當(dāng)于我們提前剪枝了,剪掉了不可能存在解的搜索子樹,這個(gè)也是剪枝的常規(guī)做法。
          大家可能感覺這個(gè)題意比較復(fù)雜,但是最后的代碼也許要比大家想的要簡單:

          class?Solution:
          ????def?isScramble(self, s1: str, s2: str)?-> bool:
          ????????from?collections import?Counter
          ????????
          ????????def?determine(s1, s2):
          ????????????# 如果s1和s2構(gòu)成的字符不同,那么直接排除
          ????????????c1 = Counter(list(s1))
          ????????????c2 = Counter(list(s2))
          ????????????return?c1 == c2

          ????????
          ????????def?dfs(s1, s2):
          ????????????# 如果要判斷的s1和s2相等,返回True
          ????????????if?s1 == s2:
          ????????????????return?True
          ????????????if?not?determine(s1, s2):
          ????????????????return?False
          ????????????n = len(s1)
          ????????????# 枚舉拆分的位置將字符串拆分成兩個(gè)部分
          ????????????for?i in?range(1, n):
          ????????????????if?dfs(s1[:i], s2[:i]) and?dfs(s1[i:], s2[i:]) or?dfs(s1[:i], s2[n-i:]) and?dfs(s1[i:], s2[:n-i]):
          ????????????????????return?True
          ????????????return?False
          ????????
          ????????????
          ????????if?len(s1) != len(s2):
          ????????????return?False
          ????????if?len(s1) == 0:
          ????????????return?True
          ????????return?dfs(s1, s2)


          總結(jié)

          今天的這道題就算是講完了,雖然看起來涉及到各種字符串的操作,又是建樹又是顛倒順序什么的,但這題本質(zhì)上其實(shí)是一道搜索題。只要對(duì)搜索問題稍微熟悉一點(diǎn),做出這道題并不困難,這也是本題通過率其實(shí)不算低的原因。
          在之前的文章當(dāng)中也曾經(jīng)提到過,不管是在LeetCode上也好,還是在acm賽場上也罷,一道看似是字符串的問題最后通過建模轉(zhuǎn)化成其他的算法模型是家常便飯的事情。大家做題的時(shí)候一定要思維靈活,如果鉆了牛角尖可能就解不出來了。
          好了,今天的文章就到這里,如果覺得有所收獲,請(qǐng)順手點(diǎn)個(gè)在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動(dòng)力。


          上期推文:

          LeetCode50-80題匯總,速度收藏!
          LeetCode刷題實(shí)戰(zhàn)81:搜索旋轉(zhuǎn)排序數(shù)組 II
          LeetCode刷題實(shí)戰(zhàn)82:刪除排序鏈表中的重復(fù)元素 II
          LeetCode刷題實(shí)戰(zhàn)83:刪除排序鏈表中的重復(fù)元素
          LeetCode刷題實(shí)戰(zhàn)84:?柱狀圖中最大的矩形
          LeetCode刷題實(shí)戰(zhàn)85: 最大矩形
          LeetCode刷題實(shí)戰(zhàn)86: 分隔鏈表

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  97在线免费视频 | 青娱乐在线视频2 | 国产aa| 久久国语 | 香蕉三级 |