From 9c3ddf2e406f1aa6f1005f2ac56eb86b807cd281 Mon Sep 17 00:00:00 2001 From: gameloader Date: Wed, 12 Feb 2025 12:23:46 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 489 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 67038a0..281d6f0 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -22492,3 +22492,492 @@ public: } }; ``` +## day328 2025-01-31 +### 827. Making A Large Island +You are given an n x n binary matrix grid. You are allowed to change at most one 0 to be 1. + +Return the size of the largest island in grid after applying this operation. + +An island is a 4-directionally connected group of 1s. + +![0131dAQAVZmcZDI3](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0131dAQAVZmcZDI3.png) + +### 题解 +本题先从头遍历数组,遇到陆地则使用bfs或者dfs遍历整个连通区域。构建一个数组,对每个连通区域中的所有陆地都用同一个大于0的数字表示,数组中的下标代表该连通区域使用的数字,数组的值表示该连通区域的陆地个数,如将第一个遇到的连通区域所有陆地都赋值为2,第二个则全部赋值为3,第三个全部赋值为4。再从头遍历数组,对于所有为0的位置,查看其四个方向的位置的值,若大于0则说明是一个区域,获得四个方向全部大于0的值对应编号区域的陆地数量(注意去重),将数量加和再加1即得该处将0变为陆地后能得到的更大连通区域中包含陆地的个数,将该值与记录的最大值比较并更新最大值。 + +### 代码 +```cpp +class Solution { +private: + vector> dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + + void dfs(vector>& grid, int x, int y, int mark, int& size) { + int n = grid.size(); + grid[x][y] = mark; + size++; + + for (const auto& dir : dirs) { + int nx = x + dir.first; + int ny = y + dir.second; + if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) { + dfs(grid, nx, ny, mark, size); + } + } + } + +public: + int largestIsland(vector>& grid) { + int n = grid.size(); + vector area(n * n + 2, 0); + int mark = 2; + + // 第一次遍历:标记不同的岛屿 + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1) { + int size = 0; + dfs(grid, i, j, mark, size); + area[mark] = size; + mark++; + } + } + } + + if (mark == 2) return 1; + if (mark == 3 && area[2] == n * n) return n * n; + + int maxArea = 0; + // 第二次遍历:尝试将0变成1 + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 0) { + // 使用数组记录相邻的岛屿标记 + int neighbors[4] = {0}; // 最多4个相邻岛屿 + int idx = 0; + + for (const auto& dir : dirs) { + int nx = i + dir.first; + int ny = j + dir.second; + if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] > 1) { + // 检查是否已经记录过这个岛屿标记 + bool found = false; + for (int k = 0; k < idx; k++) { + if (neighbors[k] == grid[nx][ny]) { + found = true; + break; + } + } + if (!found) { + neighbors[idx++] = grid[nx][ny]; + } + } + } + + // 计算将当前0变成1后的面积 + int currentArea = 1; + for (int k = 0; k < idx; k++) { + currentArea += area[neighbors[k]]; + } + maxArea = max(maxArea, currentArea); + } + } + } + + return maxArea == 0 ? area[2] : maxArea; + } +}; +``` +## day329 2025-02-01 +### 3151. Special Array I +An array is considered special if every pair of its adjacent elements contains two numbers with different parity. + +You are given an array of integers nums. Return true if nums is a special array, otherwise, return false. + +![0201OvrRgHuBWjIP](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0201OvrRgHuBWjIP.png) + +### 题解 +本题是一道简单题,只需记录前一个数字的奇偶性,将当前数字的奇偶性与前一个数字比较,如果不同则将奇偶性替换为当前数字的奇偶性。简单说即为使用长度为2的滑动窗口,保证窗口内的两个数字奇偶性不同即可,否则返回false。 + +### 代码 +```cpp +class Solution { +public: + bool isArraySpecial(vector& nums) { + for(int i=0;i& nums) { + int count = 1; + int n = nums.size(); + for(int i=0;inums[(i+1)%n]){ + count++; + } + } + return count<=2; + } +}; +``` +## day331 2025-02-03 +### 3105. Longest Strictly Increasing or Strictly Decreasing Subarray +You are given an array of integers nums. Return the length of the longest subarray of nums which is either strictly increasing or strictly decreasing. +![0203WWDm8F4e3G72](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0203WWDm8F4e3G72.png) + +### 题解 +本题是一道简单题,用一个数字记录当前递增或递减子数组的长度和当前是递增还是递减,当递增性或者递减性被打破时将该数字与记录的最大值比较并尝试更新最大值,再将数字重置为2(被打破说明有两个数字的递增递减性发生变化),若遇到下一个数字与前一个数字相同则将数字重置为1并尝试更新最大值,直到数组末尾,再次更新最大值避免漏掉到数组末尾的最后一段子数组。 + +### 代码 +```cpp +class Solution { +public: + int longestMonotonicSubarray(vector& nums) { + int result = 0; + int current = 1; + bool up = true; + for(int i=0;inums[i+1]){ + if(up){ + up = false; + result = max(result, current); + current = 2; + }else{ + current++; + } + }else if(nums[i]& nums) { + int tempsum = nums[0]; + int result = nums[0]; + for(int i=1;i s1d; + vector s2d; + for(int i=0;i2){ + return false; + } + s1d.push_back(s1[i]); + s2d.push_back(s2[i]); + } + } + + if(count==0){ + return true; + }else if(count==1){ + return false; + }else{ + if(s1d[0]==s2d[1] && s1d[1]==s2d[0]){ + return true; + } + } + return false; + } +}; +``` +## day334 2025-02-06 +### 1726. Tuple with Same Product +Given an array nums of distinct positive integers, return the number of tuples (a, b, c, d) such that a * b = c * d where a, b, c, and d are elements of nums, and a != b != c != d. + +![02064HGY0QL2amCY](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/02064HGY0QL2amCY.png) + +### 题解 +本题注意满足条件的两组数字,进行任意的位置交换都被认为是不同的元组,因此满足条件的两组数字共有8种不同的元组构成方式,则本题只要找到所有乘积相同的两组数字,将这些数字的组数乘8即得最终的结果。 + +同时发现题目中说明所有的数字均为不同的正整数,则任意两个数字相乘得到一个乘积,如果同一个乘积出现了多次,说明有不同的两数字组可以得到相同的乘积(所有数字均不相同,同一个数字不可能和两个不同数字相乘得到相同的乘积,则能得到相同的乘积两个数字必定均不相同),本题只要求计算出最终的数量而不要求列出具体的组合。则计算出数组中全部的两两相乘的乘积并放入哈希表中统计乘积出现的次数,再对出现次数大于等于2的乘积,计算从中挑选出2个的组合数,将全部组合数加和乘8即得最终结果。 + +### 代码 +```cpp +class Solution { +public: + int tupleSameProduct(vector& nums) { + unordered_map count; + for(int i=0;i& c : count){ + if(c.second >= 2){ + result += c.second*(c.second-1)/2; + } + } + return result*8; + } +}; +``` +## day335 2025-02-07 +### 3160. Find the Number of Distinct Colors Among the Balls +You are given an integer limit and a 2D array queries of size n x 2. + +There are limit + 1 balls with distinct labels in the range [0, limit]. Initially, all balls are uncolored. For every query in queries that is of the form [x, y], you mark ball x with the color y. After each query, you need to find the number of distinct colors among the balls. + +Return an array result of length n, where result[i] denotes the number of distinct colors after ith query. + +Note that when answering a query, lack of a color will not be considered as a color. + +![0207zFAL62pr2DML](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0207zFAL62pr2DML.png) + +### 题解 +本题要统计在每次染色后所有现存的球上的不同颜色有多少种。则需要记录三个数据,一个是当前所有球上共有多少种不同的颜色,另一个则是当前存在的各种颜色对应的存在的球的个数,以及不同编号的球上当前对应的颜色编号(初始默认所有球上的颜色编号均为0表示没有颜色),可以用哈希表来记录每种颜色对应的球的个数和不同球对应的颜色,对每个查询,给对应的球涂色,如果该球以前存在一个颜色,则查询哈希表并将该颜色对应的球的个数减一,如果归零则将颜色种类减一,并将新的颜色对应的球的个数加一,如果之前新的新色对应的个数为0则将颜色种类加一,将此时的颜色数作为该查询对应的结果插入数组末尾,最终返回结果数组。 + +### 代码 +```cpp +class Solution { +public: + vector queryResults(int limit, vector>& queries) { + unordered_map balls; + int count = 0; + unordered_map colors; + vector result; + for(const auto& query : queries){ + if(colors[balls[query[0]]]>0){ + if(colors[balls[query[0]]]==1){ + count--; + } + colors[balls[query[0]]] = colors[balls[query[0]]]-1; + } + if(colors[query[1]]==0){ + count++; + } + colors[query[1]] = colors[query[1]]+1; + balls[query[0]] = query[1]; + result.push_back(count); + } + return result; + } +}; +``` +## day336 2025-02-09 +### 2364. Count Number of Bad Pairs +You are given a 0-indexed integer array nums. A pair of indices (i, j) is a bad pair if i < j and j - i != nums[j] - nums[i]. + +Return the total number of bad pairs in nums. + +![0209mlm4TM4DbxKO](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0209mlm4TM4DbxKO.png) + +### 题解 +本题是一道很有意思的题目,首先可以想到与其找j-i != nums\[j\]-nums\[i\]的情况,不如找j-i == nums\[j\]-nums\[i\]的情况。因为后者大概是少数,而如果保持原来的等式形式,等式两边都同时涉及两个无关的变量,此时要计算出任意一边都必须同时知道两方的数据,而对于全部的数据,要全部计算出来只能通过暴力计算的形式全部算出,但如果简单的变换一下等式,变为j-nums\[j\]==i-nums\[i\]可以发现只是将以前的等式两边做了移项,等式仍然成立,但此时等式两边都变为了仅和同一个下标相关,在算法实现中就产生了非常大的影响,因为此时我们只需遍历一次数组,将全部i-nums\[i\]的值计算出来,统计不同差值各自的个数,对于个数大于1的差值,通过不断计算求和(假设个数为n,则满足等式条件的两两下标的组合个数为n-1+n-2+n-3...+1即n*(n-1)/2)最终即得得出全部满足j-nums\[j\]==i-nums\[i\]条件的下标组合的个数。再用该数组能得到的两两组合的总数减去满足等式条件的组合个数即得最终个数。 + +### 代码 +```cpp +class Solution { +public: + long long countBadPairs(std::vector& nums) { + std::unordered_map count; + for (int i = 0; i < nums.size(); ++i) { + count[i - nums[i]]++; + } + + long long total_pairs = (long long)nums.size() * (nums.size() - 1) / 2; + long long good_pairs = 0; + + for (auto const& [diff, freq] : count) { + if (freq > 1) { + good_pairs += (long long)freq * (freq - 1) / 2; + } + } + + return total_pairs - good_pairs; + } +}; +``` + +### 总结 +本题要注意,对于一些描述比较抽象的问题,要将题目中的一些条件和意义对应到计算机的算法当中,如i有着数组下标这一真实的数据结构含义,因此通过变换就可以优化在算法中的计算效率,这是由数组本身的特性决定的。即只能一个一个的访问,因此要在一次访问中得到尽可能最有用的信息以避免后续重复访问,如果数组计算是可以并行进行的,如能同时进行下标0和后面全部数组下标的差值及下标对应的数组值的差值的计算,则就没必要进行这样的变换处理,因为能并行的情况下也只需要n次计算就能得出最终的结果。 + +## day337 2025-02-10 +### 3174. Clear Digits +You are given a string s. + +Your task is to remove all digits by doing this operation repeatedly: + +Delete the first digit and the closest non-digit character to its left. +Return the resulting string after removing all digits. + +![0210qmCG93V9KQ1L](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0210qmCG93V9KQ1L.png) + +### 题解 +本题每次在移除数字的时候也会移除离数字最近的左侧的非数字字符,则每次碰到数字时需要移除连续的数字和紧挨着数字左侧的连续的相同个数的非数字字符,如果按照正常的从左向右访问数组,则无法预知后面连续的数字的个数,则无法确定前面要删除的非数字个数,但如果从右向左访问数组,当遇到非数字字符时就一定可以知道右侧出现了多少个数字字符。则可以将本题看成一个栈问题,遇到数字字符入栈,遇到非数字字符就删掉字符并将一个数字出栈,如果栈高度为0则保留该非数字字符,后续被保留的字符继续在之前保留字符构成的字符串的前方拼接。由于具体的数字对本题无影响,因此只需要一个变量记录栈的高度,遇到非数字字符删掉字符并减少栈的高度即可。 + +### 代码 +```cpp +class Solution { +public: + string clearDigits(string s) { + string result = ""; + int stack_height = 0; + for (int i = s.length() - 1; i >= 0; --i) { + if (isdigit(s[i])) { + stack_height++; + } else { + if (stack_height > 0) { + stack_height--; + } else { + result = s[i] + result; + } + } + } + return result; + } +}; +``` +## day338 2025-02-11 +### 1910. Remove All Occurrences of a Substring +Given two strings s and part, perform the following operation on s until all occurrences of the substring part are removed: + +Find the leftmost occurrence of the substring part and remove it from s. +Return s after removing all occurrences of part. + +A substring is a contiguous sequence of characters in a string. + +![021130kBhBDdvAVa](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/021130kBhBDdvAVa.png) + +### 题解 +本题注意在删掉一个出现的子字符串后,在该子字符串前后的字符可能会组成一个新的满足题意的子字符串,有点像消消乐在消掉一个连续图案后前后的图案可能又可以组成连续图案再次消掉,达成连击。则可以利用c++的字符串处理函数直接找到匹配part字符串的起始位置,从字符串中删掉该位置处的part字符串,再次寻找匹配part字符串的位置,如此反复直到找不到part的位置。因此s的长度并不长,因此该方法的速度也很快。 + +### 代码 +```cpp +class Solution { +public: + string removeOccurrences(string s, string part) { + while (s.find(part) != string::npos) { + s.erase(s.find(part), part.size()); + } + return s; + } +}; +``` +## day339 2025-02-12 +### 2342. Max Sum of a Pair With Equal Sum of Digits +You are given a 0-indexed array nums consisting of positive integers. You can choose two indices i and j, such that i != j, and the sum of digits of the number nums\[i] is equal to that of nums\[j]. + +Return the maximum value of nums\[i] + nums\[j] that you can obtain over all possible indices i and j that satisfy the conditions. + +![0212XJH7vnhQnfKu](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0212XJH7vnhQnfKu.png) + +### 题解 +本题可以用哈希表保存不同数字的数位和对应的最大的两个数字,在遇到新的有相同数位和的数字时将其和这两个数字比较,如果比最大值大,则更新最大值,将最大值放在次大值处,如果仅比次大值大,则仅更新次大值,计算这两个新的最大值的和并与保存的和比较。 + +### 代码 +```cpp +class Solution { +public: + int maximumSum(vector& nums) { + unordered_map> sums; + int sum = 0; + int maxsum = -1; + for(const auto& num : nums){ + sum = sumofnum(num); + if(num > sums[sum].first){ + sums[sum].second = sums[sum].first; + sums[sum].first = num; + if(sums[sum].second > 0){ + maxsum = max(maxsum,sums[sum].first+sums[sum].second); + } + }else if(num > sums[sum].second){ + sums[sum].second = num; + maxsum = max(maxsum,sums[sum].first+sums[sum].second); + } + } + return maxsum; + } + + int sumofnum(int num){ + int sum = 0; + while(num != 0){ + sum += num % 10; + num = num / 10; + } + return sum; + } +}; +```