zoukankan      html  css  js  c++  java
  • 【Word Break】cpp

    题目:

    Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

    For example, given
    s = "leetcode",
    dict = ["leet", "code"].

    Return true because "leetcode" can be segmented as "leet code".

    代码:

    class Solution {
    public:
        bool wordBreak(string s, unordered_set<string>& wordDict) {
                const int n = s.size();
                vector<vector<bool> > dp(n,vector<bool>(n,false));
                for ( int i=n-1; i>=0; --i )
                {
                    for ( int j=i; j<n; ++j )
                    {
                        for ( int k=i; k<=j; ++k )
                        {
                            if ( k==j && wordDict.find(s.substr(i,j-i+1))!=wordDict.end() )
                            {
                                dp[i][j]=true;
                            }
                            else
                            {
                                dp[i][j] = dp[i][k] && dp[k+1][j];
                                if (dp[i][j]) break;
                            }
                        }
                    }
                }
                return dp[0][n-1];
        }
    };

    tips:

    用了一个二维dp的思路。

    dp[i][j]表示s[i]到s[j]是否能被dict表示。

    dp的顺序是从后往前走,相当于是从最下往上dp上三角阵

    求递推项dp[i][j]用一个循环遍历:dp[i][k] dp[k+1][j] ( i <= k <= j )如果能找到一个使得dp[i][j]为true,则跳出。

    这里有一个corner case就是k==j的时候,dp[j+1][j]没有意义;因此特殊处理一下这种case,直接查找dict中是否有s[i:j]。

    完成之后,在思考这道题是否可以用滚动数组来做?这样空间复杂度就降低为了O(n)

    ================================================

    这个并不是滚动数组,就是一个一维DP,如下。

    class Solution {
    public:
        bool wordBreak(string s, unordered_set<string>& wordDict) {
                const int n = s.size();
                vector<bool> dp(n+1, false);
                dp[0] = true;
                for ( int i=1; i<=n; ++i )
                {
                    for ( int j=0; j<i; ++j )
                    {
                        if ( dp[j] && wordDict.find(s.substr(j,i-j))!=wordDict.end() )
                        {
                            dp[i] = true;
                            break;
                        }
                    }
                }
                return dp[n];
        }
    };

    tips:

    1. 空间复杂度由O(n²)降低到了O(n)

    2. 代码更简洁了

    并不是滚动数组,就是一维的DP,只不过dp[i]的取值要由dp[0:i-1]所有历史过程来决定。

    ===============================================

    第二次过这道题,一开始没思路,后来强迫自己想出来了一维DP的解法,最后写了出来。

    class Solution {
    public:
        bool wordBreak(string s, unordered_set<string>& wordDict) {
                bool dp[s.size()+1];
                fill_n(&dp[0], s.size()+1, false);
                dp[0] = true;
                for ( int i=1; i<=s.size(); ++i )
                {
                    if ( wordDict.find(s.substr(0,i))!=wordDict.end() )
                    {
                        dp[i] = true;
                        continue;
                    }
                    for ( int j=i-1; j>0; --j )
                    {
                        if ( dp[j] && wordDict.find(s.substr(j,i-j))!=wordDict.end() )
                        {
                            dp[i] = true;
                            break;
                        }
                    }
                }
                return dp[s.size()];
        }
    };
  • 相关阅读:
    ios更改UITabBarController背景以及选中背景图片的方法
    ios7 sdk 新特性
    AES加密算法原理
    iOS 获取手机的型号,系统版本,软件名称,软件版本
    iOS8中的UIActionSheet添加UIDatePicker后,UIDatePicker不显示问题
    iOS 8 定位失败问题
    利用CMake和OpenCV源代码生成Visual Studio工程
    dm8127前段采集和抓拍
    c++课程设计
    github安卓游戏
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4553117.html
Copyright © 2011-2022 走看看