From 664b801ca91e6e16157a6118754407344aead19c Mon Sep 17 00:00:00 2001 From: caibingcheng Date: Tue, 20 Jul 2021 21:13:10 +0800 Subject: [PATCH] =?UTF-8?q?[update]=20#3=20=E6=95=B0=E7=BB=84=E7=AF=87?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0C++=20Code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- animation-simulation/剑指offer/1的个数.md | 48 ++++++++++++--- .../数组篇/leetcode1052爱生气的书店老板.md | 60 ++++++++++++++++--- .../数组篇/leetcode41缺失的第一个正数.md | 59 +++++++++++++++--- .../数组篇/leetcode485最大连续1的个数.md | 43 +++++++++++-- .../数组篇/leetcode560和为K的子数组.md | 35 ++++++++++- 5 files changed, 215 insertions(+), 30 deletions(-) diff --git a/animation-simulation/剑指offer/1的个数.md b/animation-simulation/剑指offer/1的个数.md index d3942c2..c66a106 100644 --- a/animation-simulation/剑指offer/1的个数.md +++ b/animation-simulation/剑指offer/1的个数.md @@ -4,7 +4,7 @@ > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > -> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 +> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 今天我们来看一道贼棒的题目,题目不长,很经典,也很容易理解,我们一起来看一哈吧, @@ -87,7 +87,7 @@ 那我们将**当前位左边的定义为高位**,**当前位右边的定义位低位**。 -> 例:n = 1004 ,此时指针指向十位(当前位)num = 10,高位为百位,千位,低位为个位 +> 例:n = 1004 ,此时指针指向十位(当前位)num = 10,高位为百位,千位,低位为个位 而且我们某一位的取值范围为 0 ~ 9,那么我们可以将这 10 个数分为 3 类,小于 1 (当前位数字为 0 ),等于 1(当前位数字为 1 ) ,大于 1(当前位上数字为 2 ~ 9),下面我们就来分别考虑三种情况。 @@ -139,7 +139,7 @@ 可以继续想到密码盘,求第二段时,把前 3 位固定,只能改变最后一位。最后一位最大能到 4 ,那么共有几种情况? -### n = 1024 +### n = 1024 我们想要计算出**小于等于 1024 的非负整数中**,十位上出现 1 的次数。 @@ -187,12 +187,12 @@ class Solution { while (high != 0 || cur != 0) { cur = high % 10; high /= 10; - //这里我们可以提出 high * num 因为我们发现无论为几,都含有它 + //这里我们可以提出 high * num 因为我们发现无论为几,都含有它 if (cur == 0) count += high * num; - else if (cur == 1) count += high * num + 1 + low; + else if (cur == 1) count += high * num + 1 + low; else count += (high + 1) * num; //低位 - low = cur * num + low; + low = cur * num + low; num *= 10; } return count; @@ -209,10 +209,10 @@ class Solution { while high != 0 || cur != 0 { cur = high % 10 high /= 10 - //这里我们可以提出 high * num 因为我们发现无论为几,都含有它 + //这里我们可以提出 high * num 因为我们发现无论为几,都含有它 if cur == 0 { count += high * num - } else if cur == 1 { + } else if cur == 1 { count += high * num + 1 + low } else { count += (high + 1) * num @@ -227,5 +227,37 @@ class Solution { 时间复杂度 : O(logn) 空间复杂度 O(1) +C++ Code: +```C++ +class Solution +{ +public: + int countDigitOne(int n) + { + // 高位, 低位, 当前位 + int high = n, low = 0, cur = 0; + int count = 0, num = 1; + //数字是0的时候完全没必要继续计算 + while (high != 0) + { + cur = high % 10; + high /= 10; + //这里我们可以提出 high * num 因为我们发现无论为几,都含有它 + if (cur == 0) + count += (high * num); + else if (cur == 1) + count += (high * num + 1 + low); + else + count += ((high + 1) * num); + //低位 + low = cur * num + low; + //提前检查剩余数字, 以免溢出 + if (high != 0) + num *= 10; + } + return count; + } +}; +``` \ No newline at end of file diff --git a/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md b/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md index 79bef86..2ba1533 100644 --- a/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md +++ b/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md @@ -4,7 +4,7 @@ > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > -> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 +> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 #### [1052. 爱生气的书店老板](https://leetcode-cn.com/problems/grumpy-bookstore-owner/) @@ -48,7 +48,7 @@ rightsum 是窗口右区间的值,和左区间加和方式一样。那么我 我们此时移动了窗口, -则左半区间范围扩大,但是 leftsum 的值没有变,这时因为新加入的值,所对应的 grumpy[i] == 1,所以其值不会发生改变,因为我们只统计 grumpy[i] == 0 的值, +则左半区间范围扩大,但是 leftsum 的值没有变,这时因为新加入的值,所对应的 grumpy[i] == 1,所以其值不会发生改变,因为我们只统计 grumpy[i] == 0 的值, 右半区间范围减少,rightsum 值也减少,因为右半区间减小的值,其对应的 grumpy[i] == 0,所以 rightsum -= grumpy[i]。 @@ -72,15 +72,15 @@ class Solution { } } //窗口的值 - for (int i = 0; i < X; ++i) { - winsum += customers[i]; + for (int i = 0; i < X; ++i) { + winsum += customers[i]; } int leftsum = 0; //窗口左边缘 int left = 1; //窗口右边缘 int right = X; - int maxcustomer = winsum + leftsum + rightsum; + int maxcustomer = winsum + leftsum + rightsum; while (right < customers.length) { //重新计算左区间的值,也可以用 customer 值和 grumpy 值相乘获得 if (grumpy[left-1] == 0) { @@ -97,7 +97,7 @@ class Solution { //移动窗口 left++; right++; - } + } return maxcustomer; } } @@ -151,8 +151,54 @@ class Solution { left += 1 right += 1 } - + return maxCustomer } } ``` + +C++ Code + +```C++ +class Solution +{ +public: + int maxSatisfied(vector &customers, vector &grumpy, int minutes) + { + for_each(grumpy.begin(), grumpy.end(), [](auto &g){ g = !g; }); + vector osum(customers.size(), 0); + + //先初始化第一个元素 + osum[0] = customers[0] * grumpy[0]; + //计算前缀和, osum是origin sum + for (int i = 1; i < osum.size(); i++) + { + osum[i] = osum[i - 1] + customers[i] * grumpy[i]; + } + + //计算连续minutes的和 + vector msum(customers.size() - minutes + 1, 0); + for (int i = 0; i < minutes; i++) + { + msum[0] += customers[i]; + } + for (int i = 1; i < msum.size(); i++) + { + msum[i] = msum[i - 1] - customers[i - 1] + customers[i + minutes - 1]; + } + + //分成三段计算 + int result = 0; + for (int i = 0; i < msum.size(); i++) + { + //左 中 右 + //注意左的边界条件, 可以使用边界测试 + int sum = ((i - 1 >= 0) ? osum[i - 1] : 0) + msum[i] + osum[osum.size() - 1] - osum[i + minutes - 1]; + if (sum > result) + result = sum; + } + + return result; + } +}; +``` diff --git a/animation-simulation/数组篇/leetcode41缺失的第一个正数.md b/animation-simulation/数组篇/leetcode41缺失的第一个正数.md index e4ba3a6..784c8de 100644 --- a/animation-simulation/数组篇/leetcode41缺失的第一个正数.md +++ b/animation-simulation/数组篇/leetcode41缺失的第一个正数.md @@ -2,7 +2,7 @@ > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > -> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 +> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 #### [41. 缺失的第一个正数](https://leetcode-cn.com/problems/first-missing-positive/) @@ -53,15 +53,15 @@ class Solution { for (int x : nums) { if (x > 0 && x < res.length) { res[x] = x; - } + } } //遍历查找,发现不一样时直接返回 for (int i = 1; i < res.length; i++) { if (res[i] != i) { return i; - } + } } - //缺少最后一个,例如 1,2,3此时缺少 4 ,细节2 + //缺少最后一个,例如 1,2,3此时缺少 4 ,细节2 return res.length; } } @@ -85,7 +85,7 @@ class Solution: for i in range(1, len(res)): if res[i] != i: return i - # 缺少最后一个,例如 1,2,3此时缺少 4 ,细节2 + # 缺少最后一个,例如 1,2,3此时缺少 4 ,细节2 return len(res) ``` @@ -145,7 +145,7 @@ class Solution { for (int i = 0; i < len; ++i) { //需要考虑指针移动情况,大于0,小于len+1,不等与i+1,两个交换的数相等时,防止死循环 while (nums[i] > 0 && nums[i] < len + 1 && nums[i] != i+1 && nums[i] != nums[nums[i]-1]) { - swap(nums,i,nums[i] - 1); + swap(nums,i,nums[i] - 1); } } //遍历寻找缺失的正整数 @@ -207,10 +207,10 @@ class Solution { for i in 0.. 0 - && nums[i] < len + 1 + while nums[i] > 0 + && nums[i] < len + 1 && nums[i] != i + 1 - && nums[i] != nums[nums[i] - 1] + && nums[i] != nums[nums[i] - 1] { //nums.swapAt(i, (nums[i] - 1)) // 系统方法 self.swap(&nums, i, (nums[i] - 1)) // 自定义方法 @@ -232,3 +232,44 @@ class Solution { } } ``` + +C++ Code + +```C++ +class Solution +{ +public: + int firstMissingPositive(vector &nums) + { + int size = nums.size(); + //判断范围是否符合要求 + auto inRange = [](auto s, auto e) + { + return [s, e](auto &n) + { + return e >= n && n >= s; + }; + }; + auto cusInRange = inRange(1, size); + //增加数组长度, 便于计算, 不需要再转换 + nums.push_back(0); + + for (int i = 0; i < size; i++) + { + //将不在正确位置的元素放到正确位置上 + while (cusInRange(nums[i]) && nums[i] != i && nums[nums[i]] != nums[i]) + { + swap(nums[i], nums[nums[i]]); + } + } + + //找出缺失的元素 + for (int i = 1; i <= size; i++) + { + if (nums[i] != i) + return i; + } + return size + 1; + } +}; +``` diff --git a/animation-simulation/数组篇/leetcode485最大连续1的个数.md b/animation-simulation/数组篇/leetcode485最大连续1的个数.md index 14b9654..8e032d1 100644 --- a/animation-simulation/数组篇/leetcode485最大连续1的个数.md +++ b/animation-simulation/数组篇/leetcode485最大连续1的个数.md @@ -2,7 +2,7 @@ > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > -> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 +> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 #### [485. 最大连续 1 的个数](https://leetcode-cn.com/problems/max-consecutive-ones/) @@ -16,7 +16,7 @@ 我的这个方法比较奇怪,但是效率还可以,战胜了 100% , 尽量减少了 Math.max()的使用,我们来看一下具体思路,利用 right 指针进行探路,如果遇到 1 则继续走,遇到零时则停下,求当前 1 的个数。 -这时我们可以通过 right - left 得到 1 的 个数,因为此时我们的 right 指针指在 0 处,所以不需要和之前一样通过 right - left + 1 获得窗口长度。 +这时我们可以通过 right - left 得到 1 的 个数,因为此时我们的 right 指针指在 0 处,所以不需要和之前一样通过 right - left + 1 获得窗口长度。 然后我们再使用 while 循环,遍历完为 0 的情况,跳到下一段为 1 的情况,然后移动 left 指针。 left = right,站在同一起点,继续执行上诉过程。 @@ -125,7 +125,7 @@ class Solution { int count = 0; int maxcount = 0; - + for (int i = 0; i < nums.length; ++i) { if (nums[i] == 1) { count++; @@ -172,8 +172,43 @@ class Solution { maxCount = max(maxCount, count) count = 0 } - } + } return max(maxCount, count) } } ``` + +C++ Code + +```C++ +class Solution +{ +public: + int findMaxConsecutiveOnes(vector &nums) + { + int s = 0; + int e = 0; + int result = 0; + int size = nums.size(); + + while (s < size && e < size) + { + while (s < size && nums[s++] == 1) + { + e = s; + while (e < size && nums[e] == 1) + { + e++; + }; + //注意需要加1, 可以使用极限条件测试 + int r = e - s + 1; + if (r > result) + result = r; + s = e; + } + } + + return result; + } +}; +``` \ No newline at end of file diff --git a/animation-simulation/数组篇/leetcode560和为K的子数组.md b/animation-simulation/数组篇/leetcode560和为K的子数组.md index 6c4f372..6665d27 100644 --- a/animation-simulation/数组篇/leetcode560和为K的子数组.md +++ b/animation-simulation/数组篇/leetcode560和为K的子数组.md @@ -2,7 +2,7 @@ > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > -> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 +> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 ### [leetcode560. 和为K的子数组](https://leetcode-cn.com/problems/subarray-sum-equals-k/) @@ -114,7 +114,7 @@ class Solution { //一次遍历 for (int i = 0; i < nums.length; ++i) { //存在时,我们用数组得值为 key,索引为 value - if (map.containsKey(target - nums[i])){ + if (map.containsKey(target - nums[i])){ return new int[]{i,map.get(target-nums[i])}; } //存入值 @@ -186,3 +186,34 @@ class Solution { } } ``` + +C++ Code + +```C++ +class Solution +{ +public: + int subarraySum(vector &nums, int k) + { + unordered_map smp; + int sum = 0; + //初始化"最外面"的0 + smp[0] = 1; + int result = 0; + for(int i = 0; i < nums.size(); i++) + { + sum += nums[i]; + auto mp = smp.find(sum - k); + if (mp != smp.end()) + { + //map里面存的一定是在前面的元素 + //可以尝试将map的value换为数组 + result += mp->second; + } + smp[sum]++; + } + + return result; + } +}; +``` \ No newline at end of file