LeetCode--139. 单词拆分(动态规划)

1. 题目描述

难度:中等
在这里插入图片描述

2. 题目分析

这道题的难点在于示例3,字符串包含字典中的所有单词,但是就是无法由字典中的单词组成,要么就是多个字符,要么就是少个字符,所以在使用动态规划方法的时候要考虑这种情况的发生。
- 动态规划
我们先考虑这样一个子问题:前i个子串是否能够被字典中的单词组成,如果可以的话,我们就在这个子串的位置做一个标记,也就是将i+1记录下来,然后我们在判断第i+1到第j位的子串时候能够被匹配,如果到最后一位的子串能够被匹配,那么我们就可以判断该字符串是可以被匹配的。以示例3为例:
我们定义一个数组label来存放能够匹配的位置信息,长度与s字符串的长度相等。

  • 第一步:我们将label中的第一个元素初始化为0,也就是我们要从0开始进行判断
    在这里插入图片描述

  • 第二步:不能匹配
    在这里插入图片描述

  • 第三步:可以匹配,我们将该下标的后一位也就是3存放在label中,以便进行第二轮的判断
    在这里插入图片描述

  • 第四步:可以匹配,我们将4存放在下标中。
    在这里插入图片描述

  • 第五步:到这一步的时候,我们不仅要判断0-4之间的子串“CATSA”是否满足要求,也要判断3-4之间的子串“SA”是否满足要求,如果满足,将下标的后一位放入label数组,否则继续后移。
    在这里插入图片描述

  • 第六步:当移动到 i=6 的时候,我们的判断步骤为:

    • 0-6的子串“CATSAND”不匹配;
    • 3-6的子串“SAND”匹配;
    • 4-6的子串“AND”匹配

    只要出现匹配的情况(一次或者多次),我们都要下标 i+1存入label数组中。
    在这里插入图片描述

  • 第七步:当移动到最后一位时,我们的判断步骤为:

    • 0-8的子串“CATSANDOG”不匹配;
    • 3-8的子串“SANDOG”不匹配;
    • 4-8的子串“ANDOG”不匹配
    • 7-8的子串“OG”不匹配在这里插入图片描述
      所以最终我们得到的label数组为:
      在这里插入图片描述
      当最后一位不匹配的情况出现时,我们就可以判定该字符串是不满足条件的,所以我们可以通过判断label中数组的最后一位是否和字符串的长度相等来得出结论。

3. C语言实现

代码如下:

// 判断字符片段是否在wordDict里面
bool match(char *s, int left, int right, char ** wordDict, int wordDictSize){
    int lens = right - left + 1;
    int i = 0, j = 0;
    for(i = 0; i < wordDictSize; i++){
        if(lens == strlen(wordDict[i])){
            // 如果长度与字典中的长度一致,就判断该片段是否和字典中单词一样
            j = 0;
            while(s[left+j] == wordDict[i][j]){
                j++;
                if(j==lens) return 1;
            }
        }
    }
    return 0;
}
bool wordBreak(char * s, char ** wordDict, int wordDictSize){
    int lens = strlen(s); // 字符串的长度
    int* label = (int *)malloc(sizeof(int)*(lens+1)); //label记录能够匹配字符片段的下标
    int index = 0;
    bool res;
    label[index] = 0;
    if(lens == 1) return match(s, 0, 0, wordDict, wordDictSize);
    for(int i = 1; i <= lens; i++){
        for(int j = 0; j <= index; j++){
            // 如果子串与字典匹配,就记录该坐标并退出该循环
            if(match(s, label[j], i-1, wordDict, wordDictSize)){
                index++;
                label[index] = i;
                break;
            }
        }
    }
    res = label[index] == lens;
    free(label);  // 释放内存
    return res;
}

运行结果为:
在这里插入图片描述

4. Python实现

代码如下:

class Solution:
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: bool
        """
        if not s:
            return True
        
        breakp = [0]
        
        for i in range(len(s) + 1):
            for j in breakp:
                if s[j:i] in wordDict:
                    breakp.append(i)
                    break
        return breakp[-1] == len(s)

运行结果为:
在这里插入图片描述

发布了175 篇原创文章 · 获赞 237 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42580947/article/details/105202491
今日推荐