1. 程式人生 > >【LeetCode】87. Scramble String 解題報告(Python & C++)

【LeetCode】87. Scramble String 解題報告(Python & C++)

作者: 負雪明燭
id: fuxuemingzhu
個人部落格: http://fuxuemingzhu.cn/


目錄

題目地址:https://leetcode.com/problems/scramble-string/description/

題目描述

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = "great":

    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat"

.

    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t

We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a

We say that "rgtae" is a scrambled string of "great".

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

Example 1:

Input: s1 = "great", s2 = "rgeat"
Output: true

Example 2:

Input: s1 = "abcde", s2 = "caebd"
Output: false

題目大意

題目是混雜的字串。一個字串s1可以表達成一棵二叉樹的形式,從而把一棵二叉樹的所有葉子節點從左到右遍歷一遍就能得到源字串。現在我們要做一些翻轉二叉樹的操作,即把某些位置的二叉樹進行翻轉,這樣從左到右的葉子節點又會串成另外一個字串s2。現在要我們判斷給定s1能不能通過翻轉某些位置的二叉樹形式得到另外一個字串s2.

解題方法

遞迴

這個題某種意義上來說就是讓我們來判斷兩棵二叉樹是否能夠通過翻轉某些子樹而互相得到,也就是951. Flip Equivalent Binary Trees翻轉二叉樹子節點的題目。這個題不過是把樹變成了字串而已。

這個題的重點之一就是要合理的劃分字串從而形成兩棵不同的左右子樹,進而對左右子樹遞迴。因為事先不知道在哪裡進行分割,所以直接對每個可以劃分的位置進行遍歷分割。判斷是否兩個子串能否通過翻轉變成相等的時候,需要保證傳給函式的子串長度是相同的。因此:

  1. s1的[0:i]和s2[0:i]作為左子樹,s1[i:N]和s2[i:N]作為右子樹
  2. s1的[0:i]和s2[N - i:N]作為左子樹,s1的[i:N]和s2[0:N-i]作為右子樹

其中左子樹的兩個字串的長度都是i,右子樹的兩個字串的長度都是N - i.如果上面兩種情況有一種能夠成立,則源字串s1能夠變成s2。

由於使用了遞迴,所以終止條件一定要寫,很簡單的對長度是0、長度是1、兩個字串排序之後是否相等進行判斷。

Python程式碼如下:

class Solution(object):
    def isScramble(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        N = len(s1)
        if N == 0: return True
        if N == 1: return s1 == s2
        if sorted(s1) != sorted(s2):
            return False
        for i in range(1, N):
            if self.isScramble(s1[:i], s2[:i]) and self.isScramble(s1[i:], s2[i:]):
                return True
            elif self.isScramble(s1[:i], s2[-i:]) and self.isScramble(s1[i:], s2[:-i]):
                return True
        return False

C++程式碼如下:

class Solution {
public:
    bool isScramble(string s1, string s2) {
        if (s1.size() != s2.size()) return false;
        const int N = s1.size();
        if (N == 0) return true;
        if (N == 1) return s1 == s2;
        string s1copy = s1;
        string s2copy = s2;
        sort(s1copy.begin(), s1copy.end());
        sort(s2copy.begin(), s2copy.end());
        if (s1copy != s2copy) return false;
        for (int i = 1; i < N; i++) {
            if ((isScramble(s1.substr(0, i), s2.substr(0, i)) && isScramble(s1.substr(i), s2.substr(i))))
                return true;
            if ((isScramble(s1.substr(0, i), s2.substr(N - i)) && isScramble(s1.substr(i), s2.substr(0, N - i))))
                return true;
        }
        return false;
    }
};

動態規劃

待補。

日期

2018 年 12 月 11 日 —— 雙十一已經過去一個月了,真快啊。。