87 擾亂字串

2022-06-30 15:42:08 字數 3813 閱讀 2660

class solution:

def isscramble(self, s1: str, s2: str) -> bool:

# dp 難點分析:

# 1.首先理解三層dp分別代表:長度,s1起點,s2起點

# 2.初始化dp長度為1的dp子串

# 3.狀態轉移方程,長度為l的dp[l]可以從dp[l-k] 與 dp[k] 轉移而來

# 4.dp種幾層端點的選擇

# 1) 對於len是有實際意義的,不能為0,並且初始化時遍歷了1,所以其取值為 range(2,lens+1)

# 2) 對於端點都是從index = 0開始的,但是要保證index+l <=lens;

# 比如 lens = 10, l = 8(包括i的8個數) ,i = 0,1,2 = range(lens-l+1)

# 3) 對於分隔符號k,取值範圍為 1,l-1 因為 = range(1,l)

if sorted(s1)!=sorted(s2):

return false

if s1==s2:

return true

lens = len(s1)

dp = [[[false]*(lens) for _ in range(lens)]for _a in range(lens+1)]

for i in range(lens):

for j in range(lens):

dp[1][i][j] = s1[i] == s2[j]

for l in range(2,lens+1):

for i in range(lens-l+1):

for j in range(lens-l+1):

for k in range(1,l+1):

# 如果 l = 8, k = 2

# 沒有擾亂 s1 = i:i+2 ,i+2,i+8

# s2 = j:j+k, j+k:j+l

if dp[k][i][j] and dp[l-k][i+k][j+k]:

dp[l][i][j] = true

break

# 擾亂 s2 = j+l-k:j+l , j:j+l-k

if dp[k][i][j+l-k] and dp[l-k][i+k][j]:

dp[l][i][j] = true

break

return dp[lens][0][0]

# 遞迴,

# basecase: 兩字串相等 返回true

# 上層: 對於每乙個切分點,如果對應段相等,或者交叉相等,則返回true

# if sorted(s1) != sorted(s2):return false

# if s1 == s2 :return true

# for i in range(1,len(s1)):

# s11,s12 = s1[:i],s1[i:]

# # 正向切s2 比如長度為8 i=1分成1,7

# s21,s22 = s2[:i],s2[i:]

# if self.isscramble(s11,s21) and self.isscramble(s12,s22):

# return true

# # 反向切s2 比如長度為8 i=1分成7,1

# s21,s22 = s2[:len(s1)-i],s2[len(s1)-i:]

# if self.isscramble(s11,s22) and self.isscramble(s12,s21):

# return true

# return false

class solution:

def isscramble(self, s1: str, s2: str) -> bool:

# dp 難點分析:

# 1.首先理解三層dp分別代表:長度,s1起點,s2起點

# 2.初始化dp長度為1的dp子串

# 3.狀態轉移方程,長度為l的dp[l]可以從dp[l-k] 與 dp[k] 轉移而來

# 4.dp種幾層端點的選擇

#   1) 對於len是有實際意義的,不能為0,並且初始化時遍歷了1,所以其取值為 range(2,lens+1)

#   2)  對於端點都是從index = 0開始的,但是要保證index+l <=lens;

#       比如 lens = 10, l = 8(包括i的8個數) ,i = 0,1,2 = range(lens-l+1)

#   3) 對於分隔符號k,取值範圍為 1,l-1 因為 = range(1,l)

ifsorted(s1)!=sorted(s2):

return

false

if s1==s2:

return

true

lens = len(s1)

dp = [[[false]*(lens) for _ in

range(lens)]for _a in

range(lens+1)]

for i in

range(lens):

for j in

range(lens):

dp[1][i][j] = s1[i] == s2[j] 

for l in

range(2,lens+1):

for i in

range(lens-l+1):

for j in

range(lens-l+1):

for k in

range(1,l+1):

# 如果 l = 8, k = 2

# 沒有擾亂 s1 = i:i+2 ,i+2,i+8

#         s2 = j:j+k, j+k:j+l

if dp[k][i][j] and dp[l-k][i+k][j+k]:

dp[l][i][j] = true

break

# 擾亂   s2  = j+l-k:j+l , j:j+l-k

if dp[k][i][j+l-k] and dp[l-k][i+k][j]:

dp[l][i][j] = true

break

return dp[lens][0][0]

# 遞迴,

# basecase: 兩字串相等 返回true    

# 上層:     對於每乙個切分點,如果對應段相等,或者交叉相等,則返回true

# if sorted(s1) != sorted(s2):return false

# if s1 == s2 :return true

# for i in range(1,len(s1)):

#     s11,s12 = s1[:i],s1[i:]

#     # 正向切s2 比如長度為8 i=1分成1,7

#     s21,s22 = s2[:i],s2[i:]

#     if self.isscramble(s11,s21) and self.isscramble(s12,s22):

#         return true

#     # 反向切s2 比如長度為8 i=1分成7,1

#     s21,s22 = s2[:len(s1)-i],s2[len(s1)-i:]

#     if self.isscramble(s11,s22) and self.isscramble(s12,s21):

#         return true

# return false

leetcode87 擾亂字串

給定乙個字串 s1,我們可以把它遞迴地分割成兩個非空子字串,從而將其表示為二叉樹。下圖是字串 s1 great 的一種可能的表示形式。great gr eat g r e at a t 在擾亂這個字串的過程中,我們可以挑選任何乙個非葉節點,然後交換它的兩個子節點。例如,如果我們挑選非葉節點 gr 交...

leetcode 87 擾亂字串

給定乙個字串 s1,我們可以把它遞迴地分割成兩個非空子字串,從而將其表示為二叉樹。下圖是字串 s1 great 的一種可能的表示形式。great gr eat g r e at a t 在擾亂這個字串的過程中,我們可以挑選任何乙個非葉節點,然後交換它的兩個子節點。例如,如果我們挑選非葉節點 gr 交...

leetcode 87 擾亂字串

87.擾亂字串 沒有任何思路 直接google別人的題解,大致看懂了吧 簡單的說,就是s1和s2是scramble的話,那麼必然存在乙個在s1上的長度l1,將s1分成s11和s12兩段,同樣有s21和s22.那麼要麼s11和s21是scramble的並且s12和s22是scramble的 要麼s11...