#include <iostream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <string>
using namespace std;
int climbStairs(int n)
{
if(n < 2) return n;
vector<int>dp(n + 1);
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i <= n; ++i)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
int help(int n , vector<int>&memo)
{
if(n <= 2) return n;
if(memo[n] > 0)return memo[n];
return memo[n] = help(n-1,memo) + help(n-2,memo);
}
int climbStairsI(int n)
{
vector<int>memo(n + 1,0);
return help(n,memo);
}
int fib(int n)
{
if(n < 2) return n;
vector<int>dp(n + 1);
dp[1] = 1;
for(int i = 2; i <= n; ++i)
{
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
int dfs(int n ,vector<int>& memo)
{
if(n < 2) return n;
if(memo[n] > 0) return memo[n];
return memo[n] = dfs(n-1,memo) + dfs(n-2,memo);
}
int fibI(int n)
{
vector<int>memo(n+1);
return dfs(n,memo);
}
int numDecodings(string s)
{
if(s.empty())return 0;
int n = s.size();
vector<int>dp(n + 1);
dp[0] = 1;
dp[1] = s[0] == '0' ? 0 : 1;
for(int i = 2; i <= n; ++i)
{
int twoDigit =std::stoi( s.substr(i-2,2));
int oneDigit = std::stoi(s.substr(i-1,1));
if(10 <= twoDigit && twoDigit <= 26) dp[i]+=dp[i-2];
if(oneDigit != 0)dp[i]+=dp[i-1];
}
return dp[n];
}
bool wordbreak(string s, vector<string>&wordDict)
{
int n = s.size();
vector<int>dp(n + 1);
dp[0] = true;
unordered_set<string>set;
for(string word:wordDict)
{
set.insert(word);
}
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j < i ; ++j)
{
if(dp[j] && set.find(s.substr(j,i-j))!=set.end())
{
dp[i] = true;
break;
}
}
}
return dp[n];
}
void getResult(const vector<vector<int>>&dp,string cur,int index,string s,vector<string>&res)
{
if(0 == index)
{
res.emplace_back(cur);
return;
}
for(int preIndex:dp[index])
{
getResult(dp,s.substr(preIndex,index-preIndex) + " " + cur,preIndex,s,res);
}
}
vector<string> wordBreak(string s, vector<string>&wordDict)
{
int n = s.size();
vector<vector<int>>dp(n + 1);
dp[0].emplace_back(0);
unordered_set<string>set;
for(string word:wordDict)
{
set.insert(word);
}
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j < i; ++j)
{
if(!dp[j].empty() && set.find(s.substr(j,i-j))!=set.end())
{
dp[i].emplace_back(j);
}
}
}
vector<string>res;
getResult(dp,"",n,s,res);
return res;
}
int maxSubArray(const vector<int>& nums)
{
int maxSum = INT_MIN,maxEnd = 0, n = nums.size();
for(int i = 0; i < n; ++i)
{
maxEnd += nums[i];
maxSum = max(maxSum,maxEnd);
if(maxEnd < 0) maxEnd = 0;
}
return maxSum;
}
int maxProduct(const vector<int>& nums)
{
int n = nums.size();
vector<int>maxVal(n), minVal(n);
int res = nums[0];
maxVal[0] = nums[0], minVal[0] = nums[0];
for(int i = 1; i < n; ++i)
{
if(nums[i]>0)
{
maxVal[i] = max(maxVal[i - 1] * nums[i],nums[i]);
minVal[i] = min(minVal[i-1] * nums[i],nums[i]);
}
else
{
maxVal[i] = max(minVal[i - 1] * nums[i],nums[i]);
minVal[i] = min(maxVal[i-1] * nums[i],nums[i]);
}
res = max(res,maxVal[i]);
}
return res;
}
int lengthofList(const vector<int>& nums)
{
int n = nums.size();
if(n <= 0)return 0;
vector<int>dp(n,1);
int res = 0;
for(int i = 1; i < n; ++i)
{
for(int j = 0; j < i; ++j)
{
if(nums[j] < nums[i])dp[i] = max(dp[j] + 1, dp[i]);
}
res = max(res,dp[i]);
}
return res;
}
int minOperation(const vector<int>& target,const vector<int>& arr)
{
unordered_map<int,int>map;
for(int i = 0; i < target.size(); ++i)
{
map[target[i]] = i;
}
vector<int>nums(arr.size(),-1);
for(int i = 0; i < arr.size(); ++i)
{
if(map.find(arr[i]) != map.end())
{
nums[i] = map.at(arr[i]);
}
}
return target.size() - lengthofList(nums) + 1;
}
int main()
{
//LeetCode70
cout << climbStairs(2) << endl;
cout << climbStairs(2) << endl;
//LeetCode509
cout << fib(2) << endl;
cout << fibI(2) << endl;
//LeetCode91
string s = "12";
cout << numDecodings(s) << endl;
//LeetCode139
s = "leetcode";
vector<string>wordDict = {"leet","code"};
cout << wordbreak(s,wordDict) <<endl;
//LeetCode140
s = "catsanddog";
wordDict = {"cat","cats","and","sand","dog"};
auto res = wordBreak(s,wordDict);
for(auto str:res)
{
cout << str << endl;
}
//LeetCode53
vector<int>nums{-2,1,-3,4,-1,2,1,-5,4};
cout << maxSubArray(nums) << endl;
//LeetCode152
nums = {2,3,-2,4};
cout << maxProduct(nums) << endl;
//LeetCode300
nums = {10,9,2,5,3,7,101,18};
cout << lengthofList(nums) << endl;
//LeetCode1713
vector<int>target = {6,4,8,1,3,2};
vector<int>arr = {4,7,6,2,3,8,6,1};
cout << minOperation(target,arr) << endl;
return 0;
}