This commit is contained in:
youngyangyang04
2020-12-15 10:55:39 +08:00
parent 20229775fb
commit a332de7e08
8 changed files with 373 additions and 18 deletions

View File

@ -47,10 +47,10 @@
* 求职 * 求职
* [程序员的简历应该这么写!!(附简历模板)](https://mp.weixin.qq.com/s/nCTUzuRTBo1_R_xagVszsA) * [程序员的简历应该这么写!!(附简历模板)](https://mp.weixin.qq.com/s/nCTUzuRTBo1_R_xagVszsA)
* [BAT级别技术面试流程和注意事项都在这里了](https://mp.weixin.qq.com/s/815qCyFGVIxwut9I_7PNFw) * [BAT级别技术面试流程和注意事项都在这里了](https://mp.weixin.qq.com/s/815qCyFGVIxwut9I_7PNFw)
* [深圳原来有这么多互联网公司,你都知道么?](https://mp.weixin.qq.com/s/Yzrkim-5bY0Df66Ao-hoqA) * [深圳原来有这么多互联网公司,你都知道么?](https://mp.weixin.qq.com/s/3VJHF2zNohBwDBxARFIn-Q)
* [北京有这些互联网公司,你都知道么?](https://mp.weixin.qq.com/s/FQTzoZtqXQ2rlS1UthGrag) * [北京有这些互联网公司,你都知道么?]()
* [上海有这些互联网公司,你都知道么?](https://mp.weixin.qq.com/s/msqbX6eR2-JBQOYFfec4sg) * [上海有这些互联网公司,你都知道么?]()
* [成都有这些互联网公司,你都知道么?](https://mp.weixin.qq.com/s/Y9Qg22WEsBngs8B-K8acqQ) * [成都有这些互联网公司,你都知道么?]()
* 算法性能分析 * 算法性能分析
* [关于时间复杂度,你不知道的都在这里!](https://mp.weixin.qq.com/s/LWBfehW1gMuEnXtQjJo-sw) * [关于时间复杂度,你不知道的都在这里!](https://mp.weixin.qq.com/s/LWBfehW1gMuEnXtQjJo-sw)
@ -196,6 +196,8 @@
* [贪心算法:跳跃游戏](https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA) * [贪心算法:跳跃游戏](https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA)
* [贪心算法跳跃游戏II](https://mp.weixin.qq.com/s/kJBcsJ46DKCSjT19pxrNYg) * [贪心算法跳跃游戏II](https://mp.weixin.qq.com/s/kJBcsJ46DKCSjT19pxrNYg)
* [贪心算法K次取反后最大化的数组和](https://mp.weixin.qq.com/s/dMTzBBVllRm_Z0aaWvYazA) * [贪心算法K次取反后最大化的数组和](https://mp.weixin.qq.com/s/dMTzBBVllRm_Z0aaWvYazA)
* [本周小结!(贪心算法系列二)](https://mp.weixin.qq.com/s/RiQri-4rP9abFmq_mlXNiQ)
* [贪心算法:加油站](https://mp.weixin.qq.com/s/aDbiNuEZIhy6YKgQXvKELw)
* 动态规划 * 动态规划
@ -359,6 +361,7 @@
|[0705.设计哈希集合](https://github.com/youngyangyang04/leetcode/blob/master/problems/0705.设计哈希集合.md) |哈希表 |简单|**模拟**| |[0705.设计哈希集合](https://github.com/youngyangyang04/leetcode/blob/master/problems/0705.设计哈希集合.md) |哈希表 |简单|**模拟**|
|[0707.设计链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0707.设计链表.md) |链表 |中等|**模拟**| |[0707.设计链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0707.设计链表.md) |链表 |中等|**模拟**|
|[0763.划分字母区间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0763.划分字母区间.md) |贪心 |中等|**双指针/贪心** 体现贪心尽可能多的思想| |[0763.划分字母区间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0763.划分字母区间.md) |贪心 |中等|**双指针/贪心** 体现贪心尽可能多的思想|
|[0738.单调递增的数字](https://github.com/youngyangyang04/leetcode/blob/master/problems/0738.单调递增的数字.md) |贪心算法 |中等|**贪心算法** 思路不错,贪心好题|
|[0739.每日温度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0739.每日温度.md) |栈 |中等|**单调栈** 适合单调栈入门| |[0739.每日温度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0739.每日温度.md) |栈 |中等|**单调栈** 适合单调栈入门|
|[0767.重构字符串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0767.重构字符串.md) |字符串 |中等|**字符串** + 排序+一点贪心| |[0767.重构字符串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0767.重构字符串.md) |字符串 |中等|**字符串** + 排序+一点贪心|
|[0841.钥匙和房间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0841.钥匙和房间.md) |孤岛问题 |中等|**bfs** **dfs**| |[0841.钥匙和房间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0841.钥匙和房间.md) |孤岛问题 |中等|**bfs** **dfs**|

View File

@ -1,11 +1,41 @@
> 好了
## 思路
这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑就会顾此失彼。 # 135. 分发糖果
本题贪心贪在哪里呢? 链接https://leetcode-cn.com/problems/candy/
先确定每个孩子左边的情况(也就是从前向后遍历) 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线老师会根据每个孩子的表现预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
* 每个孩子至少分配到 1 个糖果。
* 相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
示例 1:
输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。
示例 2:
输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。
# 思路
这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,**如果两边一起考虑一定会顾此失彼**。
先确定右边评分大于左边的情况(也就是从前向后遍历)
此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
局部最优可以推出全局最优。
如果ratings[i] > ratings[i - 1] 那么[i]的糖 一定要比[i - 1]的糖多一个所以贪心candyVec[i] = candyVec[i - 1] + 1 如果ratings[i] > ratings[i - 1] 那么[i]的糖 一定要比[i - 1]的糖多一个所以贪心candyVec[i] = candyVec[i - 1] + 1
@ -22,20 +52,27 @@ for (int i = 1; i < ratings.size(); i++) {
![135.分发糖果](https://img-blog.csdnimg.cn/20201117114916878.png) ![135.分发糖果](https://img-blog.csdnimg.cn/20201117114916878.png)
再确定每个孩子右边的情况(从后向前遍历) 再确定左孩子大于右孩子的情况(从后向前遍历)
遍历顺序这里有同学可能会有疑问,为什么不能从前向后遍历呢? 遍历顺序这里有同学可能会有疑问,为什么不能从前向后遍历呢?
因为如果从前向后遍历,根据 ratings[i + 1] 来确定 ratings[i] 对应的糖果,那么每次都不能利用上前一次的比较结果了。 因为如果从前向后遍历,根据 ratings[i + 1] 来确定 ratings[i] 对应的糖果,那么每次都不能利用上前一次的比较结果了。
**所以确定每个孩子右边的情况一定要从后向前遍历!**
此时又要开始贪心,如果 ratings[i] > ratings[i + 1]就取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,**因为candyVec[i]只有取最大的才能既保持对左边candyVec[i - 1]的糖果多也比右边candyVec[i + 1]的糖果多** **所以确定左孩子大于右孩子的情况一定要从后向前遍历!**
如果 ratings[i] > ratings[i + 1]此时candyVec[i]第i个小孩的糖果数量就有两个选择了一个是candyVec[i + 1] + 1从右边这个加1得到的糖果数量一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。
那么又要贪心了局部最优取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量保证第i个小孩的糖果数量即大于左边的也大于右边的。全局最优相邻的孩子中评分高的孩子获得更多的糖果。
局部最优可以推出全局最优。
所以就取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,**candyVec[i]只有取最大的才能既保持对左边candyVec[i - 1]的糖果多也比右边candyVec[i + 1]的糖果多**。
如图: 如图:
![135.分发糖果1](https://img-blog.csdnimg.cn/20201117115658791.png) ![135.分发糖果1](https://img-blog.csdnimg.cn/20201117115658791.png)
所以代码如下: 所以该过程代码如下:
```C++ ```C++
// 从后向前 // 从后向前
@ -70,7 +107,22 @@ public:
}; };
``` ```
# 总结
这在leetcode上是一道困难的题目其难点就在于贪心的策略如果在考虑局部的时候想两边兼顾就会顾此失彼。
那么本题我采用了两次贪心的策略:
* 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
* 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。
就酱,如果感觉「代码随想录」干货满满,就推荐给身边的朋友同学们吧,关注后就会发现相见恨晚!
> **我是[程序员Carl](https://github.com/youngyangyang04)[组队刷题](https://img-blog.csdnimg.cn/20201115103410182.png)可以找我,本文[leetcode刷题攻略](https://github.com/youngyangyang04/leetcode-master)已收录,更多[精彩算法文章](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxNjY5NTYxNA==&action=getalbum&album_id=1485825793120387074&scene=173#wechat_redirect)尽在:[代码随想录](https://img-blog.csdnimg.cn/20200815195519696.png),关注后就会发现和「代码随想录」相见恨晚!** > **我是[程序员Carl](https://github.com/youngyangyang04)[组队刷题](https://img-blog.csdnimg.cn/20201115103410182.png)可以找我,本文[leetcode刷题攻略](https://github.com/youngyangyang04/leetcode-master)已收录,更多[精彩算法文章](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxNjY5NTYxNA==&action=getalbum&album_id=1485825793120387074&scene=173#wechat_redirect)尽在:[代码随想录](https://img-blog.csdnimg.cn/20200815195519696.png),关注后就会发现和「代码随想录」相见恨晚!**
**如果感觉题解对你有帮助,不要吝啬给一个👍吧!** **如果感觉题解对你有帮助,不要吝啬给一个👍吧!**

View File

@ -60,7 +60,7 @@
针对以上情形result初始为1默认最右面有一个峰值此时curDiff > 0 && preDiff <= 0那么result++计算了左面的峰值最后得到的result就是2峰值个数为2即摆动序列长度为2 针对以上情形result初始为1默认最右面有一个峰值此时curDiff > 0 && preDiff <= 0那么result++计算了左面的峰值最后得到的result就是2峰值个数为2即摆动序列长度为2
C++代码如下: C++代码如下(和上图是对应的逻辑)
```C++ ```C++
class Solution { class Solution {
@ -70,8 +70,8 @@ public:
int curDiff = 0; // 当前一对差值 int curDiff = 0; // 当前一对差值
int preDiff = 0; // 前一对差值 int preDiff = 0; // 前一对差值
int result = 1; // 记录峰值个数,序列默认序列最右边有一个峰值 int result = 1; // 记录峰值个数,序列默认序列最右边有一个峰值
for (int i = 1; i < nums.size(); i++) { for (int i = 0; i < nums.size() - 1; i++) {
curDiff = nums[i] - nums[i - 1]; curDiff = nums[i + 1] - nums[i];
// 出现峰值 // 出现峰值
if ((curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0)) { if ((curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0)) {
result++; result++;

View File

@ -0,0 +1,82 @@
# 思路
## 暴力解法
暴力一波 果然超时了
```C++
class Solution {
private:
bool checkNum(int num) {
int max = 10;
while (num) {
int t = num % 10;
if (max >= t) max = t;
else return false;
num = num / 10;
}
return true;
}
public:
int monotoneIncreasingDigits(int N) {
for (int i = N; i > 0; i--) {
if (checkNum(i)) return i;
}
return 0;
}
};
```
## 贪心算法
题目要求小于等于N的最大单调递增的整数那么拿一个两位的数字来举例。
例如98一旦出现strNum[i - 1] > strNum[i]的情况非单调递增首先想让strNum[i - 1]--然后strNum[i]给为9这样这个整数就是89即小于98的最大的单调递增整数。
这一点如果想清楚了,这道题就好办了。
**局部最优遇到strNum[i - 1] > strNum[i]的情况让strNum[i - 1]--然后strNum[i]给为9可以保证这两位变成最大单调递增整数**。
**全局最优得到小于等于N的最大单调递增的整数**。
**但这里局部最优推出全局最优还需要其他条件即遍历顺序和标记从哪一位开始统一改成9**。
此时是从前向后遍历还是从后向前遍历呢?
这里其实还有一个贪心选择对于“遇到strNum[i - 1] > strNum[i]的情况让strNum[i - 1]--然后strNum[i]给为9”的情况这个strNum[i - 1]--的操作应该是越靠后越好。
因为这样才能让这个单调递增整数尽可能的大。例如对于5486第一位的5能不减一尽量不减一因为这个减一对整体损失最大。
所以要从后向前遍历遇到strNum[i - 1] > strNum[i]的情况让strNum[i - 1]--然后strNum[i]给为9这样保证这个减一的操作尽可能在后面进行即整数的尽可能小的位数上进行
确定了遍历顺序之后,那么此时局部最优就可以推出全局,找不出反例,试试贪心。
C++代码如下:
```C++
class Solution {
public:
int monotoneIncreasingDigits(int N) {
string strNum = to_string(N);
// flag用来标记赋值9从哪里开始
// 设置为这个默认值为了防止第二个for循环在flag没有被赋值的情况下执行
int flag = strNum.size();
for (int i = strNum.size() - 1; i > 0; i--) {
if (strNum[i - 1] > strNum[i] ) {
flag = i;
strNum[i - 1]--;
}
}
for (int i = flag; i < strNum.size(); i++) {
strNum[i] = '9';
}
return stoi(strNum);
}
};
```
> **我是[程序员Carl](https://github.com/youngyangyang04),可以找我[组队刷题](https://img-blog.csdnimg.cn/20201115103410182.png),也可以在[B站上找到我](https://space.bilibili.com/525438321),本文[leetcode刷题攻略](https://github.com/youngyangyang04/leetcode-master)已收录,更多[精彩算法文章](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxNjY5NTYxNA==&action=getalbum&album_id=1485825793120387074&scene=173#wechat_redirect)尽在公众号:[代码随想录](https://img-blog.csdnimg.cn/20201124161234338.png),关注后就会发现和「代码随想录」相见恨晚!**
**如果感觉题解对你有帮助,不要吝啬给一个👍吧!**

View File

@ -0,0 +1,39 @@
(待完整)
https://www.cnblogs.com/grandyang/p/11108205.html
* 如果g >= group[k - 1]则说明犯罪k可以执行因为人数已经足够了
* 如果profit[k - 1] >= p则说明只执行犯罪k就能达到利润p可以单独执行接着我们考虑必须执行犯罪k然后加上前面的利润不低于p - profit[k - 1]的方案这样凑出的方案利润也会超过p
* 否则犯罪k不能执行此时只能直接将前面 dp[k - 1][g][p]利润超过p的方案搬过来
```
class Solution {
public:
int profitableSchemes(int G, int P, vector<int>& group, vector<int>& profit) {
int K = group.size(), MOD = 1e9 + 7;
//dp[k][g][p]使用计划[1,2,3,... k],最多g个人盈利不少于p个方案个数
vector<vector<vector<int> > > dp(K + 1, vector<vector<int> >(G + 1, vector<int>(P + 1, 0)));
for (int k = 1; k <= K; ++k){
for (int g = 1; g <= G; ++g){
for (int p = 0; p <= P; ++p){
//如果人数g能够执行第k种犯罪人数g >= 第k种犯罪需要的人数group[k - 1]
if (g >= group[k - 1]){
if (profit[k - 1] >= p){
//如果执行第k种犯罪获得的利润profit[k - 1]不小于p则可以单独执行该犯罪
dp[k][g][p] += 1;
}
//将第k个方案产生的利润profit[k]与之前方案产生的利润凑出不少于p
//dp[k - 1][g - group[k]][p > profit[k] ? p - profit[k] : 0]表示在使用[1, k - 1]这些犯罪使用人数不超过g - group[k]获得路润不少于p - profit[k]
//这样前面的产生p - profit[k]的利润再加上执行第k个犯罪的利润profit[k]就能到达到利润不少于p注意p 可能大于 profit[k],所以不能为负数)
dp[k][g][p] = (dp[k][g][p] + dp[k - 1][g - group[k - 1]][p > profit[k - 1] ? p - profit[k - 1] : 0]) % MOD;
}
//不执行第k个犯罪直接将前面的利润超过p的方案搬过来
dp[k][g][p] = (dp[k][g][p] + dp[k - 1][g][p]) % MOD;
}
}
}
return dp[K][G][P];
}
};
```

View File

@ -19,9 +19,9 @@
* [程序员的简历应该这么写!!(附简历模板)](https://mp.weixin.qq.com/s/nCTUzuRTBo1_R_xagVszsA) * [程序员的简历应该这么写!!(附简历模板)](https://mp.weixin.qq.com/s/nCTUzuRTBo1_R_xagVszsA)
* [BAT级别技术面试流程和注意事项都在这里了](https://mp.weixin.qq.com/s/815qCyFGVIxwut9I_7PNFw) * [BAT级别技术面试流程和注意事项都在这里了](https://mp.weixin.qq.com/s/815qCyFGVIxwut9I_7PNFw)
* [深圳原来有这么多互联网公司,你都知道么?](https://mp.weixin.qq.com/s/Yzrkim-5bY0Df66Ao-hoqA) * [深圳原来有这么多互联网公司,你都知道么?](https://mp.weixin.qq.com/s/Yzrkim-5bY0Df66Ao-hoqA)
* [北京有这些互联网公司,你都知道么?](https://mp.weixin.qq.com/s/FQTzoZtqXQ2rlS1UthGrag) * [北京有这些互联网公司,你都知道么?]()
* [上海有这些互联网公司,你都知道么?](https://mp.weixin.qq.com/s/msqbX6eR2-JBQOYFfec4sg) * [上海有这些互联网公司,你都知道么?]()
* [成都有这些互联网公司,你都知道么?](https://mp.weixin.qq.com/s/Y9Qg22WEsBngs8B-K8acqQ) * [成都有这些互联网公司,你都知道么?]()
* 算法性能分析 * 算法性能分析
* [关于时间复杂度,你不知道的都在这里!](https://mp.weixin.qq.com/s/LWBfehW1gMuEnXtQjJo-sw) * [关于时间复杂度,你不知道的都在这里!](https://mp.weixin.qq.com/s/LWBfehW1gMuEnXtQjJo-sw)
@ -166,6 +166,8 @@
* [贪心算法跳跃游戏II](https://mp.weixin.qq.com/s/kJBcsJ46DKCSjT19pxrNYg) * [贪心算法跳跃游戏II](https://mp.weixin.qq.com/s/kJBcsJ46DKCSjT19pxrNYg)
* [贪心算法K次取反后最大化的数组和](https://mp.weixin.qq.com/s/dMTzBBVllRm_Z0aaWvYazA) * [贪心算法K次取反后最大化的数组和](https://mp.weixin.qq.com/s/dMTzBBVllRm_Z0aaWvYazA)
* [本周小结!(贪心算法系列二)](https://mp.weixin.qq.com/s/RiQri-4rP9abFmq_mlXNiQ) * [本周小结!(贪心算法系列二)](https://mp.weixin.qq.com/s/RiQri-4rP9abFmq_mlXNiQ)
* [贪心算法:加油站](https://mp.weixin.qq.com/s/aDbiNuEZIhy6YKgQXvKELw)
(持续更新..... (持续更新.....

125
problems/数组总结篇.md Normal file
View File

@ -0,0 +1,125 @@
> 这个周末我们对数组做一个总结
# 数组理论基础
数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力
也就是说,想法很简单,但实现起来 可能就不是那么回事了。
首先要知道数组在内存中的存储方式,这样才能真正理解数组相关的面试题
**数组是存放在连续内存空间上的相同类型数据的集合。**
数组可以方便的通过下表索引的方式获取到下表下对应的数据。
举一个字符数组的例子,如图所示:
<img src='../../media/pics/算法通关数组.png' width=600> </img></div>
需要两点注意的是
* **数组下表都是从0开始的。**
* **数组内存空间的地址是连续的**
正是**因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
例如删除下表为3的元素需要对下表为3的元素后面的所有元素都要做移动操作如图所示
<img src='../../media/pics/算法通关数组1.png' width=600> </img></div>
而且大家如果使用C++的话要注意vector 和 array的区别vector的底层实现是array严格来讲vector是容器不是数组。
**数组的元素是不能删的,只能覆盖。**
那么二维数组直接上图,大家应该就知道怎么回事了
<img src='../../media/pics/算法通关数组2.png' width=600> </img></div>
**那么二维数组在内存的空间地址是连续的么?**
我们来举一个例子,例如: `int[][] rating = new int[3][4];` 这个二维数据在内存空间可不是一个 `3*4` 的连续地址空间
看了下图,就应该明白了:
<img src='../../media/pics/算法通关数组3.png' width=600> </img></div>
所以**二维数据在内存中不是 `3*4` 的连续地址空间,而是四条连续的地址空间组成!**
# 数组的经典题目
在面试中,数组是必考的基础数据结构。
其实数据的题目在思想上一般比较简单的,但是如果想高效,并不容易。
我们之前一共讲解了四道经典数组题目,每一道题目都代表一个类型,一种思想。
## 二分法
[数组:每次遇到二分法,都是一看就会,一写就废](https://mp.weixin.qq.com/s/fCf5QbPDtE6SSlZ1yh_q8Q)
这道题目呢,考察的数据的基本操作,思路很简单,但是在通过率在简单题里并不高,不要轻敌。
可以使用暴力解法,通过这道题目,如果准求更优的算法,建议试一试用二分法,来解决这道题目
暴力解法时间复杂度O(n)
二分法时间复杂度O(logn)
在这道题目中我们讲到了**循环不变量原则**,只有在循环中坚持对区间的定义,才能清楚的把握循环中的各种细节。
**二分法是算法面试中的常考题,建议通过这道题目,锻炼自己手撕二分的能力**
## 双指针法
* [数组:就移除个元素很难么?](https://mp.weixin.qq.com/s/wj0T-Xs88_FHJFwayElQlA)
双指针法(快慢指针法):**通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。**
暴力解法时间复杂度O(n^2)
双指针时间复杂度O(n)
这道题目迷惑了不少同学,纠结于数组中的元素为什么不能删除,主要是因为一下两点:
* 数组在内存中是连续的地址空间,不能释放单一元素,如果要释放,就是全释放(程序运行结束,回收内存栈空间)。
* C++中vector和array的区别一定要弄清楚vector的底层实现是array所以vector展现出友好的一些都是因为经过包装了。
双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组和链表操作的面试题,都使用双指针法。
## 滑动窗口
* [数组:滑动窗口拯救了你](https://mp.weixin.qq.com/s/UrZynlqi4QpyLlLhBPglyg)
本题介绍了数组操作中的另一个重要思想:滑动窗口。
暴力解法时间复杂度O(n^2)
滑动窗口时间复杂度O(n)
本题中,主要要理解滑动窗口如何移动 窗口起始位置,达到动态更新窗口大小的,从而得出长度最小的符合条件的长度。
**滑动窗口的精妙之处在于根据当前子序列和大小的情况不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。**
如果没有接触过这一类的方法,很难想到类似的解题思路,滑动窗口方法还是很巧妙的。
## 模拟行为
* [数组:这个循环可以转懵很多人!](https://mp.weixin.qq.com/s/KTPhaeqxbMK9CxHUUgFDmg)
模拟类的题目在数组中很常见,不涉及到什么算法,就是单纯的模拟,十分考察大家对代码的掌控能力。
在这道题目中,我们再一次介绍到了**循环不变量原则**,其实这也是写程序中的重要原则。
相信大家又遇到过这种情况: 感觉题目的边界调节超多,一波接着一波的判断,找边界,踩了东墙补西墙,好不容易运行通过了,代码写的十分冗余,毫无章法,其实**真正解决题目的代码都是简洁的,或者有原则性的**,大家可以在这道题目中体会到这一点。
# 总结
从二分法到双指针,从滑动窗口到螺旋矩阵,相信如果大家真的认真做了「代码随想录」每日推荐的题目,定会有所收获。
推荐的题目即使大家之前做过了,再读一遍的文章,也会帮助你提炼出解题的精髓所在。
如果感觉有所收获,希望大家多多支持,打卡转发,点赞在看 都是对我最大的鼓励!
最后,大家周末愉快!

View File

@ -0,0 +1,52 @@
# 数组理论基础
数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力
也就是说,想法很简单,但实现起来 可能就不是那么回事了。
首先要知道数组在内存中的存储方式,这样才能真正理解数组相关的面试题
**数组是存放在连续内存空间上的相同类型数据的集合。**
数组可以方便的通过下表索引的方式获取到下表下对应的数据。
举一个字符数组的例子,如图所示:
![算法通关数组](https://img-blog.csdnimg.cn/2020121411152849.png)
需要两点注意的是
* **数组下表都是从0开始的。**
* **数组内存空间的地址是连续的**
正是**因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
例如删除下表为3的元素需要对下表为3的元素后面的所有元素都要做移动操作如图所示
![算法通关数组1](https://img-blog.csdnimg.cn/2020121411155232.png)
而且大家如果使用C++的话要注意vector 和 array的区别vector的底层实现是array严格来讲vector是容器不是数组。
**数组的元素是不能删的,只能覆盖。**
那么二维数组直接上图,大家应该就知道怎么回事了
![算法通关数组2](https://img-blog.csdnimg.cn/20201214111612863.png)
**那么二维数组在内存的空间地址是连续的么?**
我们来举一个例子,例如: `int[][] rating = new int[3][4];` 这个二维数据在内存空间可不是一个 `3*4` 的连续地址空间
看了下图,就应该明白了:
![算法通关数组3](https://img-blog.csdnimg.cn/20201214111631844.png)
所以**二维数据在内存中不是 `3*4` 的连续地址空间,而是四条连续的地址空间组成!**
很多同学会以为二维数组在内存中是一片连续的地址,其实并不是。
这里面试中数组相关的理论知识就介绍完了。
后续我将介绍面试中数组相关的五道经典面试题目,敬请期待!