分治法
分治(divide-conquer),将原问题分解为容易求解的子问题,再对子问题合并,实现对原问题求解。
自上而下分治+记忆化搜索
自下而上(动态规划)
方法一:记忆化搜索
class Solution { public: vector<int> operand; vector<char> ops; vector<int> diffWaysToCompute(string expression) { int n=expression.size(); int i=0; while(i<n){ if(isdigit(expression[i])){ int val=0; while(i<n&&isdigit(expression[i])){ val=val*10+expression[i]-'0'; i++; } operand.push_back(val); }else{ ops.push_back(expression[i]); i++; } } vector<vector<vector<int>>> dp(operand.size(),vector<vector<int>>(operand.size())); return backtrack(dp,0,dp.size()-1); }
vector<int> backtrack(vector<vector<vector<int>>> &dp,int l,int r){ if(l==r){ return {operand[l]}; }
if(!dp[l][r].empty()) return dp[l][r];
for(int i=l;i<r;i++){ auto left=backtrack(dp,l,i); auto right=backtrack(dp,i+1,r); for(int l_val:left){ for(int r_val:right){ if(ops[i]=='+') dp[l][r].push_back(l_val+r_val); else if(ops[i]=='-') dp[l][r].push_back(l_val-r_val); else dp[l][r].push_back(l_val*r_val); } } } return dp[l][r]; } };
|
对于一个正整数 N, 我们将其等分为两部分,left 和 right, 如果 left 部分是漂亮数组,right 部分也是漂亮数组, 同时 left 部分全部是奇数,right 部分全部是偶数,那么此时 left+right 组成的数组一定也是一个漂亮数组。
class Solution { public: vector<int> beautifulArray(int n) { vector<int> ans(n,1); divide(ans,0,n-1); return ans; }
void divide(vector<int>& ans,int left,int right){ if(left>=right) return; int mid=(left+right)/2; divide(ans,left,mid); divide(ans,mid+1,right); for(int i=left;i<=mid;i++) ans[i]=ans[i]*2-1; for(int i=mid+1;i<=right;i++) ans[i]=2*ans[i]; } };
|
tag:切割出符合条件的子串,判断出现的大小写字符集
class Solution { public: int maxLen=0,pos=-1; string longestNiceSubstring(string s) { int n=s.size(); check(s,0,n-1); return maxLen==0?"":s.substr(pos,maxLen); }
void check(string &s,int left,int right){ if(left>=right) return;
int lower=0,upper=0; for(int i=left;i<=right;i++){ if(islower(s[i])){ lower|=(1<<s[i]-'a'); }else{ upper|=(1<<s[i]-'A'); } } if(lower==upper){ int len=right-left+1; if(len>maxLen){ pos=left; maxLen=len; } return; } int valid=upper&lower; int beg=left,end=left; while(end<=right){ while(end<=right&&(valid&(1<<(tolower(s[end])-'a')))) end++; check(s,beg,end-1); beg=end+1; end++; }
} };
|
class Solution { public: int ans=0; int longestSubstring(string s, int k) { int n=s.size(); check(s,0,n,k); return ans; }
void check(string &s,int left,int right,int &k){ if(left>=right) return; unordered_map<char,int> cnt; for(int i=left;i<right;i++){ cnt[s[i]]++; }
bool flag=true; int beg=left; for(int end=left;end<right;end++){ if(cnt[s[end]]<k){ flag=false; check(s,beg,end,k); beg=end+1; } }
if(flag) ans=max(ans,right-left); else check(s,beg,right,k); } };
|