【Interleaving String】cpp
题目:
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc"
,
s2 = "dbbca"
,
When s3 = "aadbbcbcac"
, return true.
When s3 = "aadbbbaccc"
, return false.
代码:
“merge sort + stack”
struct LastMatch{
int i1;
int i2;
int i3;
LastMatch(int i1, int i2, int i3): i1(i1), i2(i2), i3(i3){}
};
static bool isInterleave(string s1, string s2, string s3)
{
const int n1 = s1.size();
const int n2 = s2.size();
const int n3 = s3.size();
if ( n1+n2 != n3 ) return false;
stack<LastMatch> sta;
int i1=,i2=,i3=;
while ( i1<n1 || i2<n2 || i3<n3 )
{
if ( s1[i1]==s2[i2] && s2[i2]==s3[i3] ){
sta.push(LastMatch(i1,i2,i3));
i1++; i3++;
}
else if ( s1[i1]==s3[i3] ){
i1++; i3++;
}
else if ( s2[i2]==s3[i3] ){
i2++; i3++;
}
else if ( !sta.empty() ){
LastMatch lm = sta.top(); sta.pop();
i1 = lm.i1; i2 = lm.i2; i3 = lm.i3;
i2++; i3++;
}
else{
return false;
}
}
return i1==n1 && i2==n2 && i3==n3;
}
"dp"
class Solution {
public:
bool isInterleave(string s1, string s2, string s3)
{
const int n1 = s1.size();
const int n2 = s2.size();
const int n3 = s3.size();
if ( n1+n2 != n3 ) return false;
vector<vector<bool> > dp(n1+, vector<bool>(n2+, false));
dp[][] = true;
// check s1 boundary
for ( int i = ; i <= n1; ++i ){
dp[i][] = s1[i-]==s3[i-] && dp[i-][];
}
// check s2 boundary
for ( int i = ; i <= n2; ++i ){
dp[][i] = s2[i-]==s3[i-] && dp[][i-];
}
// dp process
for ( int i = ; i<=n1; ++i )
{
for ( int j = ; j<=n2; ++j )
{
dp[i][j] = ( s1[i-]==s3[i+j-] && dp[i-][j] )
|| ( s2[j-]==s3[i+j-] && dp[i][j-] );
}
}
return dp[n1][n2];
}
};
tips:
这道题第一版采用“merge sort + stack”,有一个大集合过不去,报超时(但即使跟可以AC的dp方法对比,“merge sort+stack”过这个大集合也仅仅慢了不到10%,在数量级上应该没有差别,时间复杂度都是O(n²))
dp的解法是学习网上的解法,理解如下:
dp[i][j]表示s1[0~i-1]与s2[0~j-1]是否匹配s3[0~i+j-1]
因此为了方便,定义dp[n+1][m+1],多一个维度,目的是保证从s1中取的个数从0到n都可以表示(s2同理)。
可以写出来dp的通项公式:
dp[i][j] = ( s1[i-1]==s3[i+j-1] && dp[i-1][j] ) || ( s2[j-1]==s3[i+j-1] && dp[i][j-1] )
表示s3第i+j个元素要么由s1匹配上,要么由s2匹配上。
最后返回dp[n1][n2]就是所需的结果。
整个dp的过程并不复杂,思考下如何得来的:
1. dp取两个维度是因为s1和s2两个变量
2. 之前自己思考dp的时候,考虑的是每个位置可以由s1或者s2其中的元素表示,但是这样考虑起来就太复杂了;网上的思路并么有考虑到这么复杂,而是仅仅考虑s3中总共就这么长字符串,某个长度的字符串可以从s1和s2各取几个。
============================================
上述的dp过程的空间复杂度是O(n²)的,再采用滚动数组方式,把空间复杂度降低到O(n),代码如下:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3)
{
const int n1 = s1.size();
const int n2 = s2.size();
const int n3 = s3.size();
if ( n1+n2 != n3 ) return false;
vector<bool> dp(n2+, false);
// check s2 boundary
dp[] = true;
for ( int i = ; i<=n2; ++i )
{
dp[i] = s2[i-]==s3[i-] && dp[i-];
}
// dp process
for ( int i = ; i<=n1; ++i )
{
dp[] = s1[i-]==s3[i-] && dp[];
for ( int j = ; j<=n2; ++j )
{
dp[j] = ( s1[i-]==s3[i+j-] && dp[j] ) || ( s2[j-]==s3[i+j-] && dp[j-] );
}
}
return dp[n2];
}
};
tips:如果二维的dp过程只跟紧上一次的dp过程有关,就可以退化为滚动数组形式的一维dp过程。
=======================================
第二次过这道题,参照dp的思路写了一遍。有个细节就是dp递推公式的时候“s3[i+j-1]”不要写成s3[i-1]或者s3[j-1]。
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if ( (s1.size()+s2.size())!=s3.size() ) return false;
bool dp[s1.size()+][s2.size()+];
fill_n(&dp[][], (s1.size()+)*(s2.size()+), false);
dp[][] = true;
for ( int i=; i<=s1.size(); ++i )
{
dp[i][] = dp[i-][] && s1[i-]==s3[i-];
}
for ( int i=; i<=s2.size(); ++i )
{
dp[][i] = dp[][i-] && s2[i-]==s3[i-];
}
for ( int i=; i<=s1.size(); ++i )
{
for ( int j=; j<=s2.size(); ++j )
{
dp[i][j] = ( dp[i-][j] && s1[i-]==s3[i+j-] ) ||
( dp[i][j-] && s2[j-]==s3[i+j-] );
}
}
return dp[s1.size()][s2.size()];
}
};
【Interleaving String】cpp的更多相关文章
- 【Scramble String】cpp
题目: Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty subs ...
- 【Valid Sudoku】cpp
题目: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could ...
- 【WildCard Matching】cpp
题目: Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single charact ...
- 【Add binary】cpp
题目: Given two binary strings, return their sum (also a binary string). For example,a = "11" ...
- 【Implement strStr() 】cpp
题目: Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if ne ...
- 【Valid Palindrome】cpp
题目: Given a string, determine if it is a palindrome, considering only alphanumeric characters and ig ...
- 【Valid Parentheses】cpp
题目: Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the ...
- 【Simplify Path】cpp
题目: Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/&quo ...
- 【Valid Number】cpp
题目: Validate if a given string is numeric. Some examples:"0" => true" 0.1 " = ...
随机推荐
- SVN Working copy '***' locked
问题描述: 用svn在项目文件夹下commit或者update时会出现错误提示“working copy locked” 解决方法: 1.在项目文件夹下,单击鼠标右键,选择tortoisesvn-&g ...
- c++编写递归函数char *itostr (int n,char *string),该函数将整数n转换为十进制表示的字符串。
#include<iostream> #include<stdio.h> using namespace std; ; char *itostr (int n,char *St ...
- DDL与DML语句
1. DDL语句 SQL语句:结构化查询语句,使用SQL与数据库“沟通”,完成相应的数据库操作. l DDL:数据定义语言,用来维护数据库对象 1.1 创建表 Ø CREATE:创建表 演示:创建员工 ...
- win10搜索不到蓝牙设备
多半是驱动不兼容的问题. 解决方法: 此电脑右键,设备管理器,然后将蓝牙下的驱动,右键.卸载设备. 安装驱动精灵,会自动检测到缺少蓝牙驱动,安装即可.
- win8.1和wp8.1共用代码,需要注意的一些问题
最近写了一个应有,使用了mvvmlight,把viewmodel.model.common之类的代码都放到了shared共享,写下来才发现,有不少问题是自已下手之前没注意到的,有些地方实在没法中途改了 ...
- POJ 1065 Wooden Sticks(LIS,最少链划分)
题意:求二维偏序的最少链划分. 用到Dilworth定理:最少链划分=最长反链.(对偶也成立,个人认为区别只是一个维度上的两个方向,写了个简单的证明 相关概念:偏序集,链,反链等等概念可以参考这里:h ...
- UVA Live Archive 4394 String painter(区间dp)
区间dp,两个str一起考虑很难转移. 看了别人题解以后才知道是做两次dp. dp1.str1最坏情况下和str2完全不相同,相当于从空白串开始刷. 对于一个区间,有两种刷法,一起刷,或者分开来刷. ...
- 动态规划专题(三)——数位DP
前言 数位\(DP\) 真的是最恶心的\(DP\). 简介 看到那种给你两个数,让你求这两个数之间符合条件的数的个数,且这两个数非常大,这样的题目一般就是 数位\(DP\) 题. 数位\(DP\)一般 ...
- Linux常用的200个命令总结分类
●目录操作命令(6 个) ls tree pwd mkdir rmdir cd ●文件操作命令(7 个) touch cp mv rm ln find rename ●文件查看及处理命令(21 ...
- python剑指offer 顺时针打印指针
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数 ...