当前位置: 首页 > news >正文

每日算法刷题Day36 6.23:leetcode枚举技巧枚举中间4道题,用时1h30min

3. 1930.长度为3的不同回文子序列(中等,学习字符串枚举26个小写字母)

1930. 长度为 3 的不同回文子序列 - 力扣(LeetCode)

思想

1.给你一个字符串 s ,返回 s 中 长度为 3 的不同回文子序列 的个数。
即便存在多种方法来构建相同的子序列,但相同的子序列只计数一次。
回文 是正着读和反着读一样的字符串。
子序列 是由原字符串删除其中部分字符(也可以不删除)且不改变剩余字符之间相对顺序形成的一个新字符串。

  • 例如,"ace" 是 "**_a_**b**_c_**d**_e_**" 的一个子序列。
  • s 仅由小写英文字母组成
    2.此题是要维护i和k的26个字符的数量,所以都要开长度为26的数组,且枚举j中的第2层枚举26个字母,用map<int, set<int>> mp;记录答案,更巧妙的要用位运算,暂时先不考虑
代码

c++:

class Solution {
public:int countPalindromicSubsequence(string s) {int n = s.size();vector<int> suf(26, 0);vector<int> pre(26, 0);for (int i = 1; i < n; ++i)++suf[s[i] - 'a'];++pre[s[0] - 'a'];map<int, set<int>> mp; // 中间字符-两侧字符for (int j = 1; j + 1 < n; ++j) {--suf[s[j] - 'a'];// 枚举26个字母for (int t = 0; t < 26; ++t) {if (pre[t] > 0 && suf[t] > 0) {mp[s[j] - 'a'].insert(t);}}++pre[s[j] - 'a'];}int res = 0;for (auto x : mp)res += x.second.size();return res;}
};
4. 3128.直角三角形(中等)

3128. 直角三角形 - 力扣(LeetCode)

思想

1.给你一个二维 boolean 矩阵 grid 。
如果 grid 的 3 个元素的集合中,一个元素与另一个元素在 同一行,并且与第三个元素在 同一列,则该集合是一个 直角三角形。3 个元素 不必 彼此相邻。
请你返回使用 grid 中的 3 个元素可以构建的 直角三角形 数目,且满足 3 个元素值  为 1 。
2.我的想法就是提前算出来(i,j)左侧,右侧,上侧和下侧1的数量,然后利用乘法原理计算,但是我一开始只考虑了右侧,没考虑左侧,所以四侧都考虑的话就直接算这一行有rowCnt个1,这一列有colCnt个1,然后乘法原理加上(rowCnt-1)*(colCnt-1)即可,这种都是要包括(i,j)元素的,我原来的想法不包括,太复杂了

代码

c++:
我的代码:

class Solution {
public:long long numberOfRightTriangles(vector<vector<int>>& grid) {int n = grid.size(), m = grid[0].size();vector<vector<int>> rightCnt(n, vector<int>(m, 0));vector<vector<int>> leftCnt(n, vector<int>(m, 0));vector<vector<int>> upCnt(n, vector<int>(m, 0));vector<vector<int>> downCnt(n, vector<int>(m, 0));for (int i = 0; i < n; ++i) {for (int j = 1; j < m; ++j) {leftCnt[i][j] =leftCnt[i][j - 1] + (grid[i][j - 1] == 1 ? 1 : 0);}}for (int i = 0; i < n; ++i) {for (int j = m - 2; j >= 0; --j) {rightCnt[i][j] =rightCnt[i][j + 1] + (grid[i][j + 1] == 1 ? 1 : 0);}}for (int j = 0; j < m; ++j) {for (int i = 1; i < n; ++i) {upCnt[i][j] = upCnt[i - 1][j] + (grid[i - 1][j] == 1 ? 1 : 0);}}for (int j = 0; j < m; ++j) {for (int i = n - 2; i >= 0; --i) {downCnt[i][j] =downCnt[i + 1][j] + (grid[i + 1][j] == 1 ? 1 : 0);}}long long res = 0;for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {if (grid[i][j] == 0)continue;res += 1LL * rightCnt[i][j] * upCnt[i][j] +1LL * rightCnt[i][j] * downCnt[i][j] +1LL * leftCnt[i][j] * upCnt[i][j] +1LL * leftCnt[i][j] * downCnt[i][j];}}return res;}
};

优化:

class Solution {
public:long long numberOfRightTriangles(vector<vector<int>>& grid) {int n = grid.size(), m = grid[0].size();vector<int> rowCnt(n, 0); // 每行1个数vector<int> colCnt(m, 0); // 每列1个数for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {if (grid[i][j] == 1) {++rowCnt[i];++colCnt[j];}}}long long res = 0;for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {if (grid[i][j] == 0)continue;res += 1LL * (rowCnt[i] - 1) * (colCnt[j] - 1);}}return res;}
};
5. 2874.有序三元组中的最大值II(中等)

2874. 有序三元组中的最大值 II - 力扣(LeetCode)

思想

1.给你一个下标从 0 开始的整数数组 nums 。
请你从所有满足 i < j < k 的下标三元组 (i, j, k) 中,找出并返回下标三元组的最大值。如果所有满足条件的三元组的值都是负数,则返回 0 。
下标三元组 (i, j, k) 的值等于 (nums[i] - nums[j]) * nums[k] 。
2.要让(nums[i] - nums[j]) * nums[k] 最大,对于固定的nums[j],即让nums[i]nums[k]最大,所以要得到最大前缀和后缀,最大前缀单变量维护即可,最大后缀数组在枚举j前得到

代码

c++:

class Solution {
public:long long maximumTripletValue(vector<int>& nums) {int n=nums.size();vector<int> suf(n,0);suf[n-1]=nums[n-1];for(int i=n-2;i>=0;--i) suf[i]=max(suf[i+1],nums[i]);int pre=nums[0];long long res=0;for(int j=1;j+1<n;++j){if(pre>nums[j] && suf[j+1]>0)   res=max(res,1LL*(pre-nums[j])*suf[j+1]);pre=max(pre,nums[j]);}return res;}
};
6. 447.回旋镖的数量(中等)

447. 回旋镖的数量 - 力扣(LeetCode)

思想

1.给定平面上 n 对 互不相同 的点 points ,其中 points[i] = [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧式距离相等(需要考虑元组的顺序)。
返回平面上所有回旋镖的数量。
2.分析题目,i与j可k无关,j和k顺序可以调换,所以两个枚举可以通过一层枚举+变量维护实现。所以第一层枚举i,通过map<long long, int> mp记录距离出现的次数,然后第二层枚举j,直接利用之前学习的有序对个数计算方法res += mp[t]++;,然后最后答案乘个2

代码

c++:

class Solution {
public:int numberOfBoomerangs(vector<vector<int>>& points) {int n = points.size();if (n < 3)return 0;int res = 0;for (int i = 0; i < n; ++i) {map<long long, int> mp; // 距离-个数for (int j = 0; j < n; ++j) {if (j == i)continue;long long t = (points[i][0] - points[j][0])*(points[i][0] - points[j][0]) +(points[i][1] - points[j][1])*(points[i][1] - points[j][1]);res += mp[t]++;}}return res * 2;}
};

相关文章:

  • 使用js做网站性能测试网上营销
  • 绍兴优秀做网站的seo外包是什么意思
  • 企业网站重要性全网引流推广 价格
  • 免费sem工具seo搜索引擎优化教程
  • 福州全网网站建设/哪家网络公司比较好
  • 网站建设的报价为什么不同/营销网站建设制作
  • VLN论文复现——VLFM(ICRA最佳论文)
  • 【图像】ubuntu中图像处理
  • 可编辑精品PPT | 企业数字化商业平台客户中台解决方案客户CRM数据中台方案
  • 支持java8的kafka版本
  • 73页精品PPT | 大数据平台规划与数据价值挖掘应用咨询项目解决方案
  • 【Docker基础】Docker容器管理:docker pause详解
  • 龙虎榜——20250623
  • AI-Sphere-Butler之如何将豆包桌面版对接到AI全能管家~新玩法(一)
  • 如何实现财务自由
  • EEG 分类攻略1- theta, alpha, beta和gamma频谱
  • 学习Linux进程冻结技术
  • OpenCV——霍夫变换
  • 一些想法。。。
  • Mermaid学习第二部
  • Unreal Engine附着组件调用区别
  • 【C语言】解决VScode中文乱码问题
  • C2远控篇PowerShell有无文件落地C#参数调用绕AMSIETW去混淆特征
  • JAVA框架有哪些?
  • Vue实现选中多张图片一起拖拽功能
  • 「Linux用户账号管理」组群管理