LeetCode: Scramble String

本文深入探讨了字符串乱序匹配问题,通过递归方法解决字符串s1与s2是否为乱序匹配的问题。详细解释了算法逻辑,包括判断条件、预剪枝策略以及递归调用过程,同时提供了Java实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

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 ifs2 is a scrambled string of s1.


这道题可以递归求解。每次递归时,首先判断:如果s1和s2相等,返回true。如果s1和s2的长度不等,返回false。接下来对s1的从1到s1.length() - 1的每一个划分点,对s1和s2做划分,递归的判断是否划分后的s1和s2的左右两部分都是scrambled string. 这个判断分两种情况,一种情况是s1划分后没有经过交换得到的s2,那么直接递归的判断划分后相对应的左右两半。还有一种情况,就是s1划分后,经过交换得到s2。在这种情况下,s1和s2的划分点需要互补,即如果s1在i划分,则s2在s2.length() - i处划分,然后递归的判断s1的左半与s2的右半和s1的右半与s2的左半。

在递归判断之前,可以做一个预判,如果s1和s2包含不同数目的字符,那么直接返回false。如果不做这个判断,大集合超时。

Java代码:

  public boolean isScramble(String s1, String s2) {
    // Start typing your Java solution below
    // DO NOT write main() function
    if (s1.equals(s2)) {
      return true;
    }
    if (s1.length() != s2.length()) {
      return false;
    }

    // Pruning
    // If s1 and s2 contain different characters, return false.
    int[] a = new int[256];
    java.util.Arrays.fill(a, 0);
    for (int i = 0; i < s1.length(); i++) {
      char c = s1.charAt(i);
      a[c - 'a']++;
    }
    for (int i = 0; i < s2.length(); i++) {
      char c = s2.charAt(i);
      a[c - 'a']--;
    }
    for (int i = 0; i < 256; i++) {
      if (a[i] != 0) {
        return false;
      }
    }
    
    for (int i = 1; i < s1.length(); i++) {
      String s1L = s1.substring(0, i);
      String s1R = s1.substring(i);

      String s2L = null;
      String s2R = null;
      
      s2L = s2.substring(0, i);
      s2R = s2.substring(i);

      if (isScramble(s1L, s2L) && isScramble(s1R, s2R)) {
        return true;
      }

      s2L = s2.substring(0, s2.length() - i);
      s2R = s2.substring(s2.length() - i);

      if (isScramble(s1L, s2R) && isScramble(s1R, s2L)) {
        return true;
      }

    }
    return false;

  }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值