20210718力扣第249场周赛(五)
力扣第249场周赛
1930. 长度为 3 的不同回文子序列
题目:
给你一个字符串 s
,返回 s
中 长度为 3 的不同回文子序列 的个数。
即便存在多种方法来构建相同的子序列,但相同的子序列只计数一次。
回文 是正着读和反着读一样的字符串。
子序列 是由原字符串删除其中部分字符(也可以不删除)且不改变剩余字符之间相对顺序形成的一个新字符串。
例如,"ace"
是 "abcde"
的一个子序列。
提示:
3 <= s.length <= 105
s
仅由小写英文字母组成
题解:
主要找到26个字母的最开始位置和最终的位置;
然后找到相同字母之间最多的不同字母数量;
然后把不同的数量统计在ans中即可。
需要会map的map.count和string s的s.size()和统计出现的不同的字母,相当于标注,用vector[i]==2(一个常量)。
代码:
1 class Solution { 2 public: 3 int countPalindromicSubsequence(string s) { 4 map<char,int> map1; 5 map<char,int> map2; 6 int n=s.size(); 7 8 for(int i=0;i<n;i++) 9 { 10 if(map1.count(s[i])==1)//不断更新字母出现在终点的位置 11 { 12 map2[s[i]]=i; 13 } 14 else 15 { 16 map1[s[i]]=i; 17 } 18 } 19 int ans=0; 20 for(char i='a';i<'a'+26;i++) 21 { 22 if(!map1.count(i) || !map2.count(i)) 23 { 24 continue; 25 } 26 int start=map1[i]; 27 int end=map2[i]; 28 vector<int> vec(26);//用vec可变数组保存相距最远的相同字母之间的不同的字母的个数,最多是26个, 29 //也就是vec最长是26的长度 30 for(int j=start+1;j<end;j++) 31 { 32 //把所有存在的可能性统计出来 33 vec[s[j]-'a']=2; 34 } 35 for(int k=0;k<26;k++) 36 { 37 if(vec[k]==2) 38 ans++; 39 } 40 41 } 42 return ans; 43 } 44 };
1931. 用三种不同颜色为网格涂色
题目:
给你两个整数 m 和 n 。构造一个 m x n 的网格,其中每个单元格最开始是白色。请你用 红、绿、蓝 三种颜色为每个单元格涂色。所有单元格都需要被涂色。
涂色方案需要满足:不存在相邻两个单元格颜色相同的情况 。返回网格涂色的方法数。因为答案可能非常大, 返回 对 109 + 7 取余 的结果。
示例 3:
输入:m = 5, n = 5 输出:580986
提示:
1 <= m <= 5
1 <= n <= 1000
题解:
此题目的m很小,只有5,所以可以从这里考虑。状态压缩dp问题。
方法一,也有代码如下,主要是分别求解出m分别等于1,2,3,4,5,的时候的状态数量。
方法二,运用动态规划,求解此题。dp[n+1][s],n+1表示列,s表示m行且一列时候的状态数量。
代码:
1 class Solution { 2 public: 3 int colorTheGrid(int m, int n) { 4 long long mod = 1000000007; 5 if(m==1) 6 { 7 int ans=3; 8 for(int i=1;i<n;++i) ans= ans * 2LL % mod; 9 return ans; 10 } 11 else if(m==2) 12 { 13 int fi = 6; 14 for(int i=1;i<n;++i) fi= 3LL * fi % mod; 15 return fi; 16 } 17 else if(m==3) 18 { 19 int fi0 = 6, fi1 = 6; 20 for (int i = 1; i < n; ++i) { 21 int new_fi0 = (2LL * fi0 + 2LL * fi1) % mod; 22 int new_fi1 = (2LL * fi0 + 3LL * fi1) % mod; 23 fi0 = new_fi0; 24 fi1 = new_fi1; 25 } 26 return ((long long)fi0 + fi1) % mod; 27 } 28 else if(m==4) 29 { 30 //ABAB//ABAC//ABCA//ABCB 31 int fi0 = 6, fi1 = 6, fi2=6, fi3=6; 32 for (int i = 1; i < n; ++i) { 33 int new_fi0 = (3LL * fi0 + 2LL * fi1+ 1LL*fi2+ 2LL*fi3) % mod; 34 int new_fi1 = (2LL * fi0 + 2LL * fi1+ 1LL*fi2+2LL*fi3) % mod; 35 int new_fi2 = (1LL * fi0 + 1LL * fi1+ 2LL*fi2 +1LL*fi3) % mod; 36 int new_fi3 = (2LL * fi0 + 2LL * fi1+ 1LL*fi2+2LL*fi3) % mod; 37 fi0 = new_fi0; 38 fi1 = new_fi1; 39 fi2 = new_fi2; 40 fi3 = new_fi3; 41 } 42 return ((long long)fi0 + fi1+ fi2+ fi3) % mod; 43 } 44 else 45 { 46 //ABABA//ABABC//ABACA//ABACB//ABCAB//ABCAC//ABCBA//ABCBC 47 int fi0 = 6, fi1 = 6, fi2=6 ,fi3 =6, fi4=6, fi5=6, fi6=6, fi7=6; 48 for (int i = 1; i < n; ++i) { 49 int new_fi0 = (3LL * fi0 + 2LL * fi1+ 2LL*fi2+ 1LL*fi3+ 0LL*fi4 +1LL*fi5 +2LL*fi6+2LL*fi7) % mod; 50 int new_fi1 = (2LL * fi0 + 2LL * fi1+ 2LL*fi2+ 1LL*fi3+ 1LL*fi4 +1LL*fi5 +1LL*fi6+1LL*fi7) % mod; 51 int new_fi2 = (2LL * fi0 + 2LL * fi1+ 2LL*fi2+ 1LL*fi3+ 0LL*fi4 +1LL*fi5 +2LL*fi6+2LL*fi7) % mod; 52 int new_fi3 = (1LL * fi0 + 1LL * fi1+ 1LL*fi2+ 2LL*fi3+ 1LL*fi4 +1LL*fi5 +1LL*fi6+1LL*fi7) % mod; 53 int new_fi4 = (0LL * fi0 + 1LL * fi1+ 0LL*fi2+ 1LL*fi3+ 2LL*fi4 +1LL*fi5 +0LL*fi6+1LL*fi7) % mod; 54 int new_fi5 = (1LL * fi0 + 1LL * fi1+ 1LL*fi2+ 1LL*fi3+ 1LL*fi4 +2LL*fi5 +1LL*fi6+1LL*fi7) % mod; 55 int new_fi6 = (2LL * fi0 + 1LL * fi1+ 2LL*fi2+ 1LL*fi3+ 0LL*fi4 +1LL*fi5 +2LL*fi6+1LL*fi7) % mod; 56 int new_fi7 = (2LL * fi0 + 1LL * fi1+ 2LL*fi2+ 1LL*fi3+ 1LL*fi4 +1LL*fi5 +1LL*fi6+2LL*fi7) % mod; 57 fi0 = new_fi0; 58 fi1 = new_fi1; 59 fi2 = new_fi2; 60 fi3 = new_fi3; 61 fi4 = new_fi4; 62 fi5 = new_fi5; 63 fi6 = new_fi6; 64 fi7 = new_fi7; 65 } 66 return ((long long)fi0 + fi1+ fi2+ fi3+ fi4 + fi5+ fi6+ fi7) % mod; 67 } 68 } 69 };
代码二:
1 class Solution { 2 public: 3 vector<vector<int>> v; 4 5 typedef long long LL; 6 int mod = 1e9 + 7; 7 8 int valid(int m)//这是m行的状态数量 9 { 10 if (m == 5) 11 for (int i = 0; i < 3; i ++) 12 for (int j = 0; j < 3; j ++) 13 for (int k = 0; k < 3; k ++) 14 for (int h = 0; h < 3; h ++) 15 for (int l = 0; l < 3; l ++) 16 if (i != j && j != k && k != h && h != l) 17 v.push_back({i, j, k, h, l}); 18 19 if (m == 4) 20 for (int i = 0; i < 3; i ++) 21 for (int j = 0; j < 3; j ++) 22 for (int k = 0; k < 3; k ++) 23 for (int h = 0; h < 3; h ++) 24 if (i != j && j != k && k != h) 25 v.push_back({i, j, k, h}); 26 27 if (m == 3) 28 for (int i = 0; i < 3; i ++) 29 for (int j = 0; j < 3; j ++) 30 for (int k = 0; k < 3; k ++) 31 if (i != j && j != k) 32 v.push_back({i, j, k}); 33 34 if (m == 2) 35 for (int i = 0; i < 3; i ++) 36 for (int j = 0; j < 3; j ++) 37 if (i != j) 38 v.push_back({i, j}); 39 40 if (m == 1) 41 for (int i = 0; i < 3; i ++) 42 v.push_back({i}); 43 44 return v.size(); 45 } 46 47 bool is_valid(int st1, int st2, int m)//判断状态是否正确 48 { 49 for (int i = 0; i < m; i ++) 50 if (v[st1][i] == v[st2][i]) return false; 51 return true; 52 } 53 54 int colorTheGrid(int m, int n) { 55 int s = valid(m); 56 LL dp[n+1][s];//注意是n+1,n会报错 57 memset(dp, 0, sizeof dp);//状态压缩DP[n+1][s]初始化为0 58 for (int i = 0; i < s; i ++) 59 { 60 dp[1][i] = 1; 61 } 62 if (n == 1) return s; 63 for (int i = 2; i <= n; i ++) 64 { 65 for (int sti = 0; sti < s; sti ++) 66 { 67 for (int stj = 0; stj < s; stj ++) 68 { 69 if (is_valid(sti, stj, m)) 70 dp[i][sti] = (dp[i][sti] + dp[i - 1][stj]) % mod;//当前列是基于前一列正确的状态,并且需要 % mod 71 } 72 } 73 } 74 75 LL ans = 0; 76 for (int i = 0; i < s; i ++) 77 { 78 ans = (ans + dp[n][i]) % mod; 79 } 80 return (int)ans; 81 } 82 };
参考链接:https://leetcode-cn.com/problems/unique-length-3-palindromic-subsequences/
https://leetcode-cn.com/problems/unique-length-3-palindromic-subsequences/solution/c-xun-zhao-hui-wen-guan-jian-huan-shi-yi-264r/
https://leetcode-cn.com/problems/painting-a-grid-with-three-different-colors/
https://leetcode-cn.com/problems/painting-a-grid-with-three-different-colors/solution/onda-cong-ming-suan-fa-tui-liao-ge-xiao-nvfk0/
https://leetcode-cn.com/problems/painting-a-grid-with-three-different-colors/solution/fei-chang-zhi-guan-de-dong-tai-gui-hua-b-f34f/