第八周(Dynamic ProgrammingII)
目录:
- 本周完成题目
- 主要过程思路
- 相关代码
一、本周完成题目
本周共完成3道题目,3道Medium。主要是继续针对于所学的Dynamic Programming选择了一些题目进行练习。
具体完成题目及难度如下表:
# | Title | Difficulty |
---|---|---|
96 | Unique Binary Search Trees | Medium |
392 | Is Subsequence | Medium |
494 | Target Sum | Medium |
题目内容
1、Unique Binary Search Trees
Given n, how many structurally unique BST’s (binary search trees) that store values 1…n?
For example,
Given n = 3, there are a total of 5 unique BST’s.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
题目大意:给定一个数字n,判断1-n一共能组成多少个二叉搜索树。
2、Is Subsequence
Given a string s and a string t, check if s is subsequence of t.
You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, “ace” is a subsequence of “abcde” while “aec” is not).
Example 1:
s = "abc", t = "ahbgdc"
Return true.
Example 2:
s = "axc", t = "ahbgdc"
Return false.
题目大意:给定两个字符串,判断字符串s是否能为t的子串(即t删除一些字符变为s,注意字符的相对位置不能变)。
3、Target Sum
You are given a list of non-negative integers, a1, a2, …, an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
There are 5 ways to assign symbols to make the sum of nums be target 3.
题目大意:给定一个数组,一个目标数字S。数组每个数字前面可以加(+)或者(-)。求经过加减之后,该数组能够等于S的数目。
二、主要过程思路
本周的题目使用到了Dynamic Programming的思想,简单来说需要从逐步到整体,动态操作最后得到需要的结果。
1、Unique Binary Search Trees:
本题结合了搜索树的构建,但是本质上来说还是动态规划的思想。
二叉搜索树的特点是左子树<根<右子树。这样对于每个根节点,其实可以分成更小的情况来计算总情况数。
显然n=1,n=0时都为1。n=2时有两种情况num[0]*num[1]+num[1]*num[0]=2。
n=3时,有num[0]*num[2] (以1为根)+num[1]*num[1] (以2为根)+num[2]*num[0] (以3为根)=5种情况。
按照这种思路推广到n的情况,即可以完成代码。
2、Is Subsequence:
本题我的思路相对比较简单。使用两个flag开始遍历字符串s和t。
flag1表示s的当前位置,flag2表示t的当前位置。如果s[flag1]==t[flag2],则令flag1向后移一位。每次比较将flag2向后移一位,直到flag1或者flag2到达末尾。
最后只需要判断flag1的大小,如果已经将s都遍历完则返回true,反之返回flase。
3、Target Sum:
这道题总体思路是逐个读数字入,记录前面所有数字出现的不同和的可能后,读入新数字时分别加入+和-两种情况的,记录下新的出现可能数组。(利用map记录)
以1,1,1,1,1为例
第一个数字:res[1]=1;res[-1]=1;
第二个数字:res[1-1]+=1;res[1+1]+=1;res[-1-1]+=1;res[-1+1]+=1。
所以新的数组为 res[0]=2;res[2]=1;res[-2]=1。
第三个数字:结果为res[1]=3,res[-1]=3;res[3]=1;res[-3]=1。
这里需要注意的是,由于每次实际上是生成了一个新的map res,所以在操作的时候需要增加一个res2来保存新的map,之后再将res2的值赋给res。
三、相关代码
Unique Binary Search Trees
class Solution {
public:
int numTrees(int n) {
int numOftree[n+1]={0};
numOftree[0]=numOftree[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
numOftree[i]+=numOftree[j-1]*numOftree[i-j];
}
}
return numOftree[n];
}
};
Is Subsequence
class Solution {
public:
bool isSubsequence(string s, string t) {
int l1=s.length();
int l2=t.length();
if(l1>l2) return false;
int flag1=0,flag2=0;
while(flag1<l1&&flag2<l2){
if(s[flag1]==t[flag2]){
flag1++;
}
flag2++;
}
if(flag1==l1) return true;
else return false;
}
};
Target Sum
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
map<int,int> res;
res[nums[0]]++; res[-nums[0]]++;
for(int i=1;i<nums.size();i++){
map<int,int> res2;
for(auto p:res){
int sum=p.first,count=p.second;
res2[sum+nums[i]]+=count;
res2[sum-nums[i]]+=count;
}
res=res2;
}
return res[S];
}
};