算法总结:连续子串
来源:互联网 发布:软件设计师视频教程 编辑:程序博客网 时间:2024/06/14 22:30
求子串满足某一条件的问题一般可以转化为先求以第i(0 < i <=n)个元素结尾满足该条件的解,然后将所有解加起来即可得到原问题的解。正是因为我们将以每个元素作为结尾来定义解,所以可以包含所有解,并且不会重复。
例子
求一个数组中连续子数组中任何数字出现次数不大于k的所有子数组
1 2 2 4
1
答案是6
1、2、2、4、1 2、2 4
要求出所有满足条件的子数组,只要求出以nums[i]结尾的满足条件的所有数组长度的和。用上面的例子说明一下:
当 i = 0 时以1结尾的满足条件的数组长度是1,满足条件的子数组是[1]
当 i = 1 时以2结尾的满足条件的数组长度是2 即[1, 2],满足条件的子数组是[2]、[1, 2]
当 i = 2 时以2结尾的满足条件的数组长度是1 即[2],满足条件的子数组是[2](这个2和i=1时的2不是一个2,没有重复)
当 i = 3 时以4结尾的满足条件的数组长度是2 即[2,4],满足条件的子数组是[4]、[2, 4]
实现代码
#include <iostream>#include <unordered_map>#include <vector>#include <algorithm>using namespace std;int main(int argc, char const *argv[]){ int k; int count; cin >> count; //输入元素个数 cin >> k; if(k == 0){ cout << 0 << endl; return 0 ; } vector<int> nums; for(int i = 0; i < count; i++) { int elem; cin >> elem; nums.push_back(elem); } unordered_map<int, int> hash; std::vector<int> dp(count, 0); //i 和 j分别代表子数组的头部和尾部 for(int i = 0,j = 0; j < count; j++) { ++hash[nums[j]]; //如果满足条件子数组长度加1 if(hash[nums[j]] <= k) { dp[j] = j - i + 1; } 如果不满足条件,说明nums[j]出现的次数大于了k。此时移动i直到去除一个nums[j]为止,这样子数组中nums[j]的个数就为k,满足条件。 else { --hash.[nums[i++]]; while(nums[i-1] != nums[j]) { --hash[nums[i++]]; } dp[j] = j - i + 1; } } int sum = accumulate(dp.begin(), dp.end(), 0); cout << sum << endl; return 0;}
Arithmetic Slices
已知一个数组,求这个数组中可以切割出多少个长度大于3的连续等差数列
A = [1, 2, 3, 4]
return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
和第一个题一样,求出每个以nums[i]结尾的解即可
因为子数组长度要大于3所以从i=2开始 res[0] = 0, dp[1] = 0;
当i = 2 时[1, 2, 3] 满足条件所以dp[2] = 1
当i = 3 时[2, 3, 4]、[1, 2, 3, 4]满足条件所以dp[2] = 2
答案是0 + 0 +1 + 2 = 3;
注意到dp[i]和dp[i-1]的关系
以[1, 2, 3, 4, 5]为例,以4结尾的大于等于3的等差数列加上一个5肯定是满足要求的,[3, 4]不满足要求,但[3, 4, 5]满足,所以如果nums[i] - nums[i-1] == nums[i-1]-nums[i - 2] 那么dp[i] = dp[i-1]+1;否则dp[i]=0;因此没有必要每次去找满足条件的最长子数组,用这个状态转移方程就可以了。最后把结果加起来就可以了。
代码如下
class Solution {public: int numberOfArithmeticSlices(vector<int>& A) { int n = A.size(); if (n < 3) return 0; vector<int> dp(n, 0); if (A[2]-A[1] == A[1]-A[0]) dp[2] = 1; int result = dp[2]; for (int i = 3; i < n; ++i) { if (A[i]-A[i-1] == A[i-1]-A[i-2]) dp[i] = dp[i-1] + 1; result += dp[i]; } return result; }};
- 算法总结:连续子串
- 【算法小总结】最大连续子序列和最大连续子矩阵的关系与实现
- 最长连续公共子串算法
- 最长连续公共子串算法
- 最长公共子串(连续)算法
- 【算法】最大连续乘积子串
- 最长公共子串与最长连续子串算法
- 算法 | 最大连续子数组
- 算法---连续子数组和
- 最大连续子序列总结
- poj 2406 D3C 算法 后缀数组 连续重复子串
- poj 3974 Palindrome 【最长连续回文子串,Manacher算法】
- 算法:输出给定字符串的全部连续子串
- 《算法导论》-最大公共子串(连续) C语言版
- 经典字符串算法 “最长上升子序列,最大连续子序列和,最长公共子串”
- 连续子串
- 最大连续子串
- 算法导论 - 最大和连续子数组
- 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字
- HDOJ1213. How many tables(并查集连通块计数)
- java指定小数点后位数格式
- php 删除文件夹 以及 文件夹所有文件
- 2017年JD后台岗面经总结-1(不是我的面经)
- 算法总结:连续子串
- 栈(Stack)
- LZ Fix the first bug
- 百度等搜索引擎智能提示(JSONP跨域实现自动补全搜索建议)
- Log4net系列一:Log4net搭建之文本格式输出
- Idea使用
- 八大排序算法
- ORACLE 数据文件丢失处理
- Java必懂之Java内存分配