Merge branch 'chefyuan:main' into main

This commit is contained in:
Jared Liw Zhi Long 2021-07-23 18:41:18 +08:00 committed by GitHub
commit b553da68cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 215 additions and 30 deletions

View File

@ -4,7 +4,7 @@
> >
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助 > 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
> >
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入 > 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入
今天我们来看一道贼棒的题目题目不长很经典也很容易理解我们一起来看一哈吧 今天我们来看一道贼棒的题目题目不长很经典也很容易理解我们一起来看一哈吧
@ -87,7 +87,7 @@
那我们将**当前位左边的定义为高位****当前位右边的定义位低位** 那我们将**当前位左边的定义为高位****当前位右边的定义位低位**
> n = 1004 此时指针指向十位当前位num = 10高位为百位千位低位为个位 > n = 1004 此时指针指向十位当前位num = 10高位为百位千位低位为个位
而且我们某一位的取值范围为 0 ~ 9,那么我们可以将这 10 个数分为 3 小于 1 当前位数字为 0 等于 1当前位数字为 1 大于 1当前位上数字为 2 ~ 9下面我们就来分别考虑三种情况 而且我们某一位的取值范围为 0 ~ 9,那么我们可以将这 10 个数分为 3 小于 1 当前位数字为 0 等于 1当前位数字为 1 大于 1当前位上数字为 2 ~ 9下面我们就来分别考虑三种情况
@ -139,7 +139,7 @@
可以继续想到密码盘求第二段时把前 3 位固定只能改变最后一位最后一位最大能到 4 那么共有几种情况 可以继续想到密码盘求第二段时把前 3 位固定只能改变最后一位最后一位最大能到 4 那么共有几种情况
### n = 1024 ### n = 1024
我们想要计算出**小于等于 1024 的非负整数中**十位上出现 1 的次数 我们想要计算出**小于等于 1024 的非负整数中**十位上出现 1 的次数
@ -187,12 +187,12 @@ class Solution {
while (high != 0 || cur != 0) { while (high != 0 || cur != 0) {
cur = high % 10; cur = high % 10;
high /= 10; high /= 10;
//这里我们可以提出 high * num 因为我们发现无论为几都含有它 //这里我们可以提出 high * num 因为我们发现无论为几都含有它
if (cur == 0) count += 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; else count += (high + 1) * num;
//低位 //低位
low = cur * num + low; low = cur * num + low;
num *= 10; num *= 10;
} }
return count; return count;
@ -209,10 +209,10 @@ class Solution {
while high != 0 || cur != 0 { while high != 0 || cur != 0 {
cur = high % 10 cur = high % 10
high /= 10 high /= 10
//这里我们可以提出 high * num 因为我们发现无论为几都含有它 //这里我们可以提出 high * num 因为我们发现无论为几都含有它
if cur == 0 { if cur == 0 {
count += high * num count += high * num
} else if cur == 1 { } else if cur == 1 {
count += high * num + 1 + low count += high * num + 1 + low
} else { } else {
count += (high + 1) * num count += (high + 1) * num
@ -227,5 +227,37 @@ class Solution {
时间复杂度 : O(logn) 空间复杂度 O(1) 时间复杂度 : 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;
}
};
```

View File

@ -4,7 +4,7 @@
> >
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助 > 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
> >
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入 > 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入
#### [1052. 爱生气的书店老板](https://leetcode-cn.com/problems/grumpy-bookstore-owner/) #### [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] 右半区间范围减少rightsum 值也减少因为右半区间减小的值其对应的 grumpy[i] == 0所以 rightsum -= grumpy[i]
@ -72,15 +72,15 @@ class Solution {
} }
} }
//窗口的值 //窗口的值
for (int i = 0; i < X; ++i) { for (int i = 0; i < X; ++i) {
winsum += customers[i]; winsum += customers[i];
} }
int leftsum = 0; int leftsum = 0;
//窗口左边缘 //窗口左边缘
int left = 1; int left = 1;
//窗口右边缘 //窗口右边缘
int right = X; int right = X;
int maxcustomer = winsum + leftsum + rightsum; int maxcustomer = winsum + leftsum + rightsum;
while (right < customers.length) { while (right < customers.length) {
//重新计算左区间的值也可以用 customer 值和 grumpy 值相乘获得 //重新计算左区间的值也可以用 customer 值和 grumpy 值相乘获得
if (grumpy[left-1] == 0) { if (grumpy[left-1] == 0) {
@ -97,7 +97,7 @@ class Solution {
//移动窗口 //移动窗口
left++; left++;
right++; right++;
} }
return maxcustomer; return maxcustomer;
} }
} }
@ -151,8 +151,54 @@ class Solution {
left += 1 left += 1
right += 1 right += 1
} }
return maxCustomer return maxCustomer
} }
} }
``` ```
C++ Code
```C++
class Solution
{
public:
int maxSatisfied(vector<int> &customers, vector<int> &grumpy, int minutes)
{
for_each(grumpy.begin(), grumpy.end(), [](auto &g){ g = !g; });
vector<int> 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<int> 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;
}
};
```

View File

@ -2,7 +2,7 @@
> >
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助 > 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
> >
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入 > 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入
#### [41. 缺失的第一个正数](https://leetcode-cn.com/problems/first-missing-positive/) #### [41. 缺失的第一个正数](https://leetcode-cn.com/problems/first-missing-positive/)
@ -53,15 +53,15 @@ class Solution {
for (int x : nums) { for (int x : nums) {
if (x > 0 && x < res.length) { if (x > 0 && x < res.length) {
res[x] = x; res[x] = x;
} }
} }
//遍历查找,发现不一样时直接返回 //遍历查找,发现不一样时直接返回
for (int i = 1; i < res.length; i++) { for (int i = 1; i < res.length; i++) {
if (res[i] != i) { if (res[i] != i) {
return i; return i;
} }
} }
//缺少最后一个例如 123此时缺少 4 细节2 //缺少最后一个例如 123此时缺少 4 细节2
return res.length; return res.length;
} }
} }
@ -85,7 +85,7 @@ class Solution:
for i in range(1, len(res)): for i in range(1, len(res)):
if res[i] != i: if res[i] != i:
return i return i
# 缺少最后一个例如 123此时缺少 4 细节2 # 缺少最后一个例如 123此时缺少 4 细节2
return len(res) return len(res)
``` ```
@ -145,7 +145,7 @@ class Solution {
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
//需要考虑指针移动情况大于0小于len+1不等与i+1两个交换的数相等时防止死循环 //需要考虑指针移动情况大于0小于len+1不等与i+1两个交换的数相等时防止死循环
while (nums[i] > 0 && nums[i] < len + 1 && nums[i] != i+1 && nums[i] != nums[nums[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..<len { for i in 0..<len {
// 需要考虑指针移动情况大于0小于len+1不等与i+1 // 需要考虑指针移动情况大于0小于len+1不等与i+1
// 两个交换的数相等时防止死循环 // 两个交换的数相等时防止死循环
while nums[i] > 0 while nums[i] > 0
&& nums[i] < len + 1 && nums[i] < len + 1
&& nums[i] != i + 1 && nums[i] != i + 1
&& nums[i] != nums[nums[i] - 1] && nums[i] != nums[nums[i] - 1]
{ {
//nums.swapAt(i, (nums[i] - 1)) // 系统方法 //nums.swapAt(i, (nums[i] - 1)) // 系统方法
self.swap(&nums, 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<int> &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;
}
};
```

View File

@ -2,7 +2,7 @@
> >
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助 > 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
> >
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入 > 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入
#### [485. 最大连续 1 的个数](https://leetcode-cn.com/problems/max-consecutive-ones/) #### [485. 最大连续 1 的个数](https://leetcode-cn.com/problems/max-consecutive-ones/)
@ -16,7 +16,7 @@
我的这个方法比较奇怪但是效率还可以战胜了 100% , 尽量减少了 Math.max()的使用我们来看一下具体思路利用 right 指针进行探路如果遇到 1 则继续走遇到零时则停下求当前 1 的个数 我的这个方法比较奇怪但是效率还可以战胜了 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站在同一起点继续执行上诉过程 然后我们再使用 while 循环遍历完为 0 的情况跳到下一段为 1 的情况然后移动 left 指针 left = right站在同一起点继续执行上诉过程
@ -125,7 +125,7 @@ class Solution {
int count = 0; int count = 0;
int maxcount = 0; int maxcount = 0;
for (int i = 0; i < nums.length; ++i) { for (int i = 0; i < nums.length; ++i) {
if (nums[i] == 1) { if (nums[i] == 1) {
count++; count++;
@ -172,8 +172,43 @@ class Solution {
maxCount = max(maxCount, count) maxCount = max(maxCount, count)
count = 0 count = 0
} }
} }
return max(maxCount, count) return max(maxCount, count)
} }
} }
``` ```
C++ Code
```C++
class Solution
{
public:
int findMaxConsecutiveOnes(vector<int> &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;
}
};
```

View File

@ -2,7 +2,7 @@
> >
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助 > 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
> >
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入 > 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步想要和题友一起刷题互相监督的同学可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入
### [leetcode560. 和为K的子数组](https://leetcode-cn.com/problems/subarray-sum-equals-k/) ### [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) { for (int i = 0; i < nums.length; ++i) {
//存在时我们用数组得值为 key索引为 value //存在时我们用数组得值为 key索引为 value
if (map.containsKey(target - nums[i])){ if (map.containsKey(target - nums[i])){
return new int[]{i,map.get(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<int> &nums, int k)
{
unordered_map<int, int> 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;
}
};
```