204场周赛

5500. 乘积为正数的最长子数组长度

解题思路:

我们使用两个数组来进行动态规划,分别为p_dp[i]:以 i 结尾乘积为正数得最长子数组长度 n_dp[i]:以 i 结尾乘积为负数得最长子数组长度。当nums[i]为不同情况时,每个数组得不同操作如下:

  • nums[i] > 0时,p_dp[i] = p_dp[i - 1] + 1即可。n_dp[i] 要根据n_dp[i - 1] 是否存在负数得最长子数组,若存在则乘上一个正数还是负数所以n_dp[i] = n_dp[i - 1] + 1,若不存在则n_dp[i] = 0
  • nums[i] < 0时,p_dp[i]要根据n_dp[i - 1],因为若以i - 1结尾乘积为负数得最长子数组长度乘上一个负数,则肯定为以 i 结尾乘积为正数得最长子数组长度。同样得道理,n_dp[i] 根据 p_dp[i - 1]乘上一个负数得到最长子数组长度。
  • nums[i] == 0时,p_dp和n_dp都不会选择得,所以全部重置为0即可

代码:

class Solution {
public:int getMaxLen(vector<int>& nums) {int sz = nums.size();vector<int> p_dp(sz);vector<int> n_dp(sz);p_dp[0] = nums[0] > 0 ? 1 : 0;n_dp[0] = nums[0] < 0 ? 1 : 0;int res = p_dp[0];for(int i = 1; i < sz; i++) {if(nums[i] > 0) {p_dp[i] = p_dp[i - 1] + 1;n_dp[i] = n_dp[i - 1] > 0 ? n_dp[i - 1] + 1 : 0;} else if(nums[i] < 0) {p_dp[i] = n_dp[i - 1] > 0 ? n_dp[i - 1] + 1 : 0;n_dp[i] = p_dp[i - 1] + 1;} else {p_dp[i] = 0;n_dp[i] = 0;}res = max(res , p_dp[i]);}return res;}
};

总结:

  1. 这里得dp数组每个都是局部求解,因为在遇到0时,我们全部重置了,重置后得结果可能不是最优解,所以我们不能直接返回p_dp[sz - 1],要使用res单独存储起来,每次都更新。
  2. 这题得难点不在于动态规划得思想,在于两个不同状态得切换求值,当nums[i] > 0 或者nums[i] < 0时,如果通过另一个状态来求得该状态得值。我们只是把两种状态使用数组表示而已

1568. 使陆地分离的最少天数

解题思路:

设置check函数判断是否只存在一个岛屿,我们只要检查是否删除一个陆地后都都会存在一个岛屿,那么我们只要找到一个相邻有4条边得陆地,删除以它和它得对角一个陆地,即可分离出两个岛屿了。

代码:

class Solution {
public:int dx[4] = {1 , 0 , -1 , 0};int dy[4] = {0 , 1 , 0 , -1};bool isInside(const vector<vector<int>>& grid , int x , int y) {return x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size();}bool check(const vector<vector<int>>& grid) {int x , y , count = 0;for(int i = 0; i < grid.size(); i++) {for(int j = 0; j < grid[i].size(); j++) {if(grid[i][j] == 0)     continue;count++;x = i;y = j;}}queue<pair<int , int>> q;bool mark[30][30] = {0};q.push(make_pair(x , y));mark[x][y] = true;count--;while(!q.empty()) {auto f = q.front();q.pop();for(int i = 0; i < 4; i++) {int nx = f.first + dx[i] , ny = f.second + dy[i];if(isInside(grid , nx , ny) && grid[nx][ny] == 1) {if(mark[nx][ny])    continue;mark[nx][ny] = true;q.push(make_pair(nx , ny));count--;}}}return count != 0;}int minDays(vector<vector<int>>& grid) {if(check(grid))     return 0;for(int i = 0; i < grid.size(); i++) {for(int j = 0; j < grid[i].size(); j++) {if(grid[i][j] == 0)     continue;grid[i][j] = 0;if(check(grid))     return 1;grid[i][j] = 1;}}return 2;}
};

总结:

这题更像是一道思维题,当发现最多只要2步操作得时候,这题就AC了。这道题得时间复杂度为 O(n^4)

1569. 将子数组重新排序得到同一个二叉查找树的方案数

代码:

class Solution {
public:const long long mod = 1000000007;long long com[1001][1001];long long combine(int a , int b) {return com[a][b];}void dfs(vector<int>& nums , int L , int R , long long &mul) {if(R - L + 1 <= 2)  return;vector<int> less , greater;for(int i = L + 1; i <= R; i++) {if(nums[i] < nums[L])   less.push_back(nums[i]);else    greater.push_back(nums[i]);}mul *= combine(less.size() + greater.size() , greater.size());if(mul >= mod)   mul %= mod;dfs(less , 0 , less.size() - 1 , mul);dfs(greater , 0 , greater.size() - 1 , mul);}int numOfWays(vector<int>& nums) {com[1][0] = com[1][1] = 1;for(int i = 2; i <= 1000; i++) {com[i][0] = 1;for(int j = 1; j <= i; j++) {com[i][j] = (com[i - 1][j] + com[i - 1][j - 1]) % mod;}}long long mul = 1;dfs(nums , 0 , nums.size() - 1, mul);return (mul - 1 + mod) % mod;}
};

34场双周赛

5492. 分割字符串的方案数

解题思路:

对于没有1的字符串,就是排列组合问题,一共有 种可能。

对于有1的字符串,若1的数量不能被3整除时,直接返回0。否则就是计算第一个字符串结尾和第二个字符开头有多少个0字符串再加1,再计算第二个字符串结尾和第三个字符串开发之间有多少个0字符串再加1。两数相乘即可得到答案

代码:

class Solution {
public:const int mod = 1000000007;int numWays(string s) {bool flag = true;long long res = 0;int num = 0;for(int i = 0; i < s.size(); i++) {if(s[i] == '1') {flag = false;num++;}}if(flag) {long long sz = s.size();res =  (sz - 1) * (sz - 2) / 2;return res % mod;}if(num % 3 != 0) {return 0;}int both = num / 3;long long temp1 = 1 , temp2 = 1 , temp = 0;for(int i = 0; i < s.size(); i++) {if(s[i] == '1' && both) {both--;} else if(s[i] == '0' && !both) {temp++;} else if(s[i] == '1' && !both) {if(temp1 == 1)  temp1 = temp + 1;else if(temp2 == 1)  temp2 = temp + 1;temp = 0;both = num / 3 - 1;}}res = temp1 * temp2;res %=  mod;return res;}
};

总结:

这题在我比赛时,死在了没有1的情况下,不知道如何算出,我直接使用加法进行计算。

5493. 删除最短的子数组使剩余数组有序

解题思路:

  1. 找到两端的有序子数组
  2. 合并两个数组成为一个新的有序数组,计算影响成为有序数组数据的数量
  3. 计算无序数组的数量
  4. 返回影响成为有序数组数据的数量+无序数组的数量

代码:

class Solution {
public:int findLengthOfShortestSubarray(vector<int>& arr) {int n = arr.size();int i = 0;for(; i < n - 1; i++) {if(arr[i] > arr[i + 1])     break;}int left = i;if(left == n - 1)   return 0;i = n - 1;for(; i > 0; i--) {if(arr[i] < arr[i - 1])   break;}int right = i;if(right - left == n - 1) {if(arr[right] >= arr[left])     return n - 2;return n - 1;}if(arr[left] <= arr[right])     return right - left - 1;int l = 0 , r = right , cnt = 0;while(l < left + 1 && r < n) {if(arr[l] > arr[r]) {cnt++;l++;r++;} else {l++;}}return right - left - 1 + cnt;}
};

总结:

  1. left == n - 1,证明数组本身就是个有序数组,直接返回0
  2. right - left == n - 1,证明数组除开头尾就是一个反序数组。然后判断arr[right]和arr[left]
    1. 若arr[left]和arr[right]能组成一个有序数组,则返回n - 2
    2. 否则返回n - 1
  3. 当arr[left] <= arr[right],证明左端有序数组的结尾与右端有序数组的开头能组成有序数组,直接删除中间的无需数组即可

5494. 统计所有可行路径

解题思路:

每种求路径数量的问题都可以使用动态规划来解决。问题就是如何设置dp数组和函数逻辑。

dp[i][j]表示当前起点为i,剩余油量j的总方案数。

因为这个路径可以重复走无数次,所以我们的结束条件就是不重复计算即可。

代码:

typedef long long ll;
int dp[105][205];
const int mod = 1e9 + 7;class Solution {
public:int dfs(vector<int>& locations , int start , int finish , int fuel) {if(dp[start][fuel] != -1)      return dp[start][fuel];ll res = 0;if(start == finish)     res++;int len = locations.size();for(int i = 0; i < len; i++) {int diff = abs(locations[i] - locations[start]);if(start == i)      continue;if(fuel - diff >= 0) {res = (res + dfs(locations , i , finish , fuel - diff)) % mod;}}dp[start][fuel] = res % mod;return dp[start][fuel];}int countRoutes(vector<int>& locations, int start, int finish, int fuel) {memset(dp , -1 , sizeof(dp));return dfs(locations , start , finish , fuel);}
};

总结:

  1. 必须要在类内初始化一下,如果不初始化,默认数组中的数就为0,但是dp[start][fuel] == 0,可能会出现重复计算的情况

这题其实不难,或者说动态规划的题大部分都不难,主要是找到dp数组的参数设置,然后就是空间和时间的优化。这些都是动态规划中涉及的。

第205场周赛

1577. 数的平方等于两数乘积的方法数

解题思路:

直接用两个哈希表来存储数组中每个数的平方值的个数,最后根据nums1[i] * nums1[j]的值为索引值找到个数,nums2同理可得

代码:

class Solution {
public:int numTriplets(vector<int>& nums1, vector<int>& nums2) {map<long long , int> mli1 , mli2;int res = 0;for(auto i : nums1)  mli1[(long long) 1 * i * i]++;for(auto i : nums2)  mli2[(long long) 1 * i * i]++;for(int i = 0; i < nums1.size(); i++) {for(int j = i + 1; j < nums1.size(); j++) {res += mli2[(long long) 1 * nums1[i] * nums1[j]];}}for(int i = 0; i < nums2.size(); i++) {for(int j = i + 1; j < nums2.size(); j++) {res += mli1[(long long) 1 * nums2[i] * nums2[j]];}}return res;}
};

总结:

这题使用哈希表存储平方数值的个数方法解决,比赛时想到用的是递归方法,想得非常的复杂,其实是道水题

1578. 避免重复字母的最小删除成本

解题思路:

当遇到重复字母时,我们使用贪心思想,选择当前两个中的较小成本的字母进行”删除“。当“删除”的字母是i + 1时,因为i + 1可能会影响到后面的成本计算,所以把i + 1和 i 的成本交换一下,相当于删除的是永远是前面一个重复数,并且是成本较小的。

代码:

class Solution {
public:int minCost(string s, vector<int>& cost) {int res = 0 , n = s.size();for(int i = 0; i < n - 1; i++) {if(s[i] == s[i + 1]) {res += min(cost[i] , cost[i + 1]);if(cost[i] > cost[i + 1])   swap(cost[i] , cost[i + 1]);}}return res;}
};

总结:

这里的贪心思想如何转换成对于全局都适用的规律呢,就是swap(cost[i] , cost[i + 1])。当我们遇到3个或者多个相同的数时,我总是比较当前的两个,无法想到如何顾及到后面较小的成本值。这就是解决方法。

Leetcode周赛专题相关推荐

  1. C/C++描述 LeetCode 周赛 第199场周赛(阿里云专场)

    C/C++描述 LeetCode 周赛 第199场周赛(阿里云专场)   大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在CSDN ...

  2. [LeetCode周赛复盘] 第 314 场周赛20221009

    [LeetCode周赛复盘] 第 314 场周赛20221009 一.本周周赛总结 二. [Easy] 6201. 找出前缀异或的原始数组 1. 题目描述 2. 思路分析 3. 代码实现 三.[Eas ...

  3. leetcode周赛5465. 子树中标签相同的节点数

    leetcode周赛5465. 子树中标签相同的节点数 给你一棵树(即,一个连通的无环无向图),这棵树由编号从 0 到 n - 1 的 n 个节点组成,且恰好有 n - 1 条 edges .树的根节 ...

  4. 我也是LeetCode周赛“三道题选手”啦 第270场周赛

    第270场周赛小结 我的Weekly Contest 270战况 什么是LeetCode周赛? show my code! 复盘解决Hard题 我的Weekly Contest 270战况 参加周赛有 ...

  5. [LeetCode周赛复盘] 第 89 场双周赛20221015

    [LeetCode周赛复盘] 第 89 场双周赛20221015 一.本周周赛总结 二. [Easy] 6208. 有效时间的数目 1. 题目描述 2. 思路分析 3. 代码实现 三.[Medium] ...

  6. [LeetCode周赛复盘] 第 324 场周赛20221218

    [LeetCode周赛复盘] 第 324 场周赛20221218 一.本周周赛总结 二. [Easy] 6265. 统计相似字符串对的数目 1. 题目描述 2. 思路分析 3. 代码实现 三.[Med ...

  7. [LeetCode周赛复盘] 第 310 场周赛20220911

    [LeetCode周赛复盘] 第 310 场周赛20220911 一.本周周赛总结 二. [Easy] 6176. 出现最频繁的偶数元素 1. 题目描述 2. 思路分析 3. 代码实现 三.[Medi ...

  8. leetcode探索专题中的初级算法练习题(python代码+解题思路)

    本文记录leetcode探索专题中的初级算法练习题,附python实现代码&解题思路,做题过程不免查阅网络资料,侵删~如有错误,欢迎指正交流! 目录 专题一:数组: 26.从排序数组中删除重复 ...

  9. 宝宝也能看懂的 leetcode 周赛 - 174 - 3

    1339. 分裂二叉树的最大乘积 Hi 大家好,我是张小猪.欢迎来到『宝宝也能看懂』系列之 leetcode 周赛题解. 这里是第 174 期的第 3 题,也是题目列表中的第 1339 题 -- 『分 ...

最新文章

  1. 条件随机场CRF简介Introduction to Conditional Random Fields
  2. 使用Idea创建SpringCloud父子工程
  3. VTK:Utilities之Timer
  4. 开源纯C#工控网关+组态软件(五)从网关到人机界面
  5. JavaScript中的位置协议属性
  6. linux内核那些事之mmap_region流程梳理
  7. 淘宝直播应关注哪些方面?
  8. 怎么一键重装系统?装机大师一键重装图文教程
  9. python实现基于selenium的天猫淘宝秒杀,支持定金商品,自动付款
  10. 2018 年计算机语言排行榜,TIOBE:2018年11月编程语言排行榜
  11. Python网络爬虫精要
  12. 21.BOM的理解,常见的BOM对象你了解哪些?
  13. 【border相关】【P3426】 [POI2005]SZA-Template
  14. 固高jog运动和点位运动
  15. pull时出现错误及解决方法
  16. AD拼版工具 Embedded board array 进行PCB拼版注意事项
  17. [VOT15](2021CVPR)Alpha-Refine: Boosting Tracking Performance by Precise Bounding Box Estimation
  18. 兄弟姐妹们,有没有啥开源的项目能加一下我吗?
  19. 关于传奇聚灵珠Gom脚本的详细说明讲解
  20. 网络撮合交易的大市场

热门文章

  1. 微软文档外泄:Xbox 720、Kinect 2以及Kinect Glasses抢先看
  2. 雷林鹏:一个90后草根创业者的野蛮生长
  3. 数独游戏的两种编程思路+代码
  4. soap java实现_java使用soap方式简单实现webservice (二)
  5. 如何用python显示出所有能被17整除的数_怎样判定一个数能被17整除
  6. wps日期加减算天数_WPS表格计算这个月的剩余天数的公式
  7. php注册表唯一电脑,windows 注册表里注册自己的协议(原创)
  8. 详解CSS float属性
  9. java 密码检测_Java工具集-密码检测工具
  10. 【转载】iphone九宫格界面实现