[算法练习]leetcode

编程入门 行业动态 更新时间:2024-10-07 12:28:11

[<a href=https://www.elefans.com/category/jswz/34/1770096.html style=算法练习]leetcode"/>

[算法练习]leetcode

题目链接

力扣

字符串的 引力 定义为:字符串中 不同 字符的数量。

例如,"abbca" 的引力为 3 ,因为其中有 3 个不同字符 'a'、'b' 和 'c' 。
给你一个字符串 s ,返回 其所有子字符串的总引力 。

子字符串 定义为:字符串中的一个连续字符序列。

示例 1:

输入:s = "abbca"
输出:28
解释:"abbca" 的子字符串有:
- 长度为 1 的子字符串:"a"、"b"、"b"、"c"、"a" 的引力分别为 1、1、1、1、1,总和为 5 。
- 长度为 2 的子字符串:"ab"、"bb"、"bc"、"ca" 的引力分别为 2、1、2、2 ,总和为 7 。
- 长度为 3 的子字符串:"abb"、"bbc"、"bca" 的引力分别为 2、2、3 ,总和为 7 。
- 长度为 4 的子字符串:"abbc"、"bbca" 的引力分别为 3、3 ,总和为 6 。
- 长度为 5 的子字符串:"abbca" 的引力为 3 ,总和为 3 。
引力总和为 5 + 7 + 7 + 6 + 3 = 28 。

来源:力扣(LeetCode)
链接:
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

所有的连续子数组是[i, j]  i <= j 的组合,直接枚举所有情况,是O(N^2)的时间复杂度,

可以考虑使用动态规划来分析,假设f(i)是以第i个元素为起始点的所有情况,

f(0) = [0, 0], [0,1], [0,2], [0,3] …… 

f(1) =  [1,1], [1,2], [1,3] ……

可以看到,f(1)的结果可以从f(0)推导出来,分为a[0] == a[1]和a[0] != a[1]的情况,

按照这个思路,可以这样写

class Solution {
public:long long appealSum(string s) {//init, get sum and each poslong long f = 0;map<int, vector<int>> pos;int len = s.size();for (int i = 0; i < len; i++) {int k = s[i];pos[k].push_back(i);f += pos.size();}long long ans = f;vector<int> dt(len);vector<long long> fs(len);dt[0] = 0;fs[0] = f;for (int i = 0; i < len-1; i++) {//f1 = f0 - dtint c = s[i];if (s[i] == s[i+1]) {fs[i+1] = fs[i] - 1;ans += fs[i+1];continue;}//find the pos of ivector<int>& arr = pos[c];int b = 0;int e = arr.size()-1;int p = e+1;while (b <= e) {int m = (b+e)/2;if (arr[m] > i) {e = m-1;p = m;} else {b = m+1;}}int d = len - i;if (p <= arr.size()-1) {d = arr[p] - i;}fs[i+1] = fs[i] - d;ans += fs[i+1];}     return ans;   }
};

对于这个题目,也可以假设f(i)是以a[i]为末尾的情况,这样处理,程序写起来更清楚一些,

上面的题目是求>=1的个数,下面的题目比较相似,是求==1的数量,采用f(i)是以a[i]为末尾的情况来处理,

力扣

class Solution {
public:int uniqueLetterString(string s) {const int n = s.size();int tt = 1000000000+7;//1.// dp[i]: 以s[i]结尾的子字符串的总引力// pre_idx[i]: 记录字符 'a'+i 之前出现的位置,如果之前没有出现,就 = -1long long dp[n];vector<vector<int>> pre_idx(26, vector<int>(2, -1));//    int pre_idx[26][2] = {-1};//just the first one is -1// 2. initialdp[0] = 1;int c = s[0] - 'A';pre_idx[c][1] = 0;// 3. long long ans = 1;for (int i = 1; i < n; ++i) {c = s[i] - 'A'; char of pos i//    int len = i - pre_idx[s[i] - 'A'] - 1;int dt = 0;//not appeared begforeif (pre_idx[c][1] == -1) {dt = i+1;} else {dt = (i-pre_idx[c][1])- (pre_idx[c][1]-pre_idx[c][0]); // (pre_idx[c][1]-pre_idx[c][0]) //new// - (i-pre_idx[c][0]);//old}dp[i] = dp[i - 1] + dt;pre_idx[c][0] = pre_idx[c][1];pre_idx[c][1] = i;//if (dp[i] > tt) {dp[i] = dp[i]%tt;}ans += dp[i];}// 4. return ans%tt;}
};

另外子数组的题目,需要考虑使用单调栈找左右区间,

力扣

更多推荐

[算法练习]leetcode

本文发布于:2024-02-25 17:49:38,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1699813.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:算法   leetcode

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!