归并递归至底,再从底至上合并结果
一般用于存在重复子结构的问题
一般能用归并的题都可以用动态规划,不过动态规划不容易想到,归并不错
给个例题,将区间划分为多个子区间,使得所有区间拥有的回文子串和最少
input
aacabbcbadabcbh
output
5
解释
a aca b bcbadabcb h
#include <bits/stdc++.h>
using namespace std;
int helper(string str, int i, int j, int l, int r){
while (i>=l && j<=r && str[i]==str[j]){
i--; j++;
}
return j-i-1;
}
void mergefunc(string str, int l, int r, int &res){
if (l > r)
return;
int start=0, end=0;
for (int i=l; i<=r; i++){
int len1 = helper(str, i, i, l, r);
int len2 = helper(str, i, i+1, l, r);
if (max(len1, len2) > end-start){
start = i - (max(len1, len2)+1)/2;
end = i + max(len1, len2)/2;
}
}
res++;
mergefunc(str, l, start, res);
mergefunc(str, end+1, r, res);
}
int main(){
string str;
while (cin >> str){
int res = 0;
mergefunc(str, 0, str.length()-1, res);
cout << res << endl;
}
return 0;
}
不得不说,归并是真的很神奇的方法,你只需要切分,不用去管怎么合并的。
一道笔试题,也是使用归并
对于一个数组,找到两个不重叠的子数组,长度和最小。每个子数组和均为T
input
arr:3 1 5 2 4
T:4
output
3
解释
两个子数组分别为3,1和4,所以长度和为3
#include <bits/stdc++.h>
using namespace std;
using Pair = pair<int, int>;
Pair findT(vector<int> arr, int T, int l, int r){
queue<int> que;//滑动窗口利用队列
int sum = 0; int start=INT_MIN+1, end=INT_MAX-1; int res = INT_MAX;
for (int i=l; i<=r; i++){
sum += arr[i]; que.push(i);
while (!que.empty() && sum > T){
sum -= arr[que.front()];
que.pop();
}
if (sum == T){
sum -= arr[que.front()];
if (res > i-que.front()){
res = min(res, i-que.front());
start = que.front(); end = i;//记录子数组的前后下标
}
que.pop();
}
}
return {start, end};
}
void merge(vector<int>& A, int T, int l, int r, vector<int>& res){
if (l > r) return;
Pair temp = findT(A, T, l, r);
if (temp.first != INT_MIN+1)
res.push_back(temp.second-temp.first+1);//存储满足的子数组的长度
merge(A, T, l, temp.first-1, res);
merge(A, T, temp.second+1, r, res);
}
void minSumOfLengths(vector<int>& A, int T) {
vector<int> res;
merge(A, T, 0, A.size()-1, res);
sort(res.begin(), res.end());
if (res.size() < 2 || res[0] == INT_MIN+1) {
cout << -1 << endl;
return;
}
cout << res[0]+res[1] << endl;//取最小两个元素
}
int main(){
vector<int> A; int i;
while (cin >> i) A.push_back(i);
int T = A.back(); A.pop_back();
minSumOfLengths(A, T);
return 0;
}