这段时间在刷一些编程题过程中,对解题思路的总结,也会不断更新这个博客,希望能对大家有所帮助!
1、双指针:
这里的指针并不是真正的指针,对于数组而言,把下标当作指针,将数组划分为三个部分,[0,des]为已经处理部分,[des,cur]为已经处理部分,[cur+1,n-1]未处理部分。
总结:双指针算法是先设定两个元素下标(des和cur),其中cur遍历数组,des来安置元素,[0,des]表示安置完了的元素,将nums[cur]满足要求的元素往nums[des]中搬。
2、滑动窗口:
初始化left和right -> 进窗口 -> 判断 -> (更新结果)-> 出窗口 (循环)
满足数字和达到要求长度最短的数组,用right遍历数组,利用好数字之和事递增的性质来完成,指针的滑动。
无重复字符串的数组:Hash[128]可以映射所有字符。
总结:滑动窗口,就是设计双指针(left和right),其中right作为遍历数组的下标,不断进窗口,然后根据满足特殊要求(一般是个while循环)来更新结果并且让一些不必要的元素出窗口,出窗口的元素以left为下标,遍历完数组即找到我们需要的结果。
3、二分算法:
针对有无序数组均可以使用,只要能找到规律(二段性)。
步骤:(1)朴素的二分模板
(2)查找左边界的二分模板:循环条件:left<right;中点求法:left+(right-left)/2
(3)查找右边界的二分模板:循环条件:left<right;中点求法:left+(right-left+1)/2
细节处理:
循环条件和求中点的方式。
题目分析:首先判断是否二段性,然后根据二段性来划分左右区间的特点,定左右边界。
题目:
(2)34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
如果是一个无重复的元素具有二段性的数组,直接用朴素的二分查找;有重复则用左右区间查找法。如果是山脉求山峰的问题,那么直接改判断条件,用mid和mid-1或者+1比较判断是在峰值左边还是右边。
4、前缀和:
一维数组求和:
dp数组从下标为1开始计数可以方便处理边界问题dp[i-1]中i= 0的情况,看清楚要处理的dp范围。因为dp数组中存放的前缀和只需要下标做减法就可以求出指定范围和。
二维数组求和;
5、位运算:
1.基础位运算
>> << ~ & | ^
2.给一个数n,判断它的二进制表示中的第x位是0还是1
(n>>x)&1;
3.将一个数n的二进制表示的第x位修改成1
n=n|(1<<x)
4.将一个数n的二进制表示的第x位修改成0
n = n&(~(1<<x))
5.位图思想
哈希表+上面操作
6.提取n最右边的1
n&(-n) (-n)就是将n先取反然后+1
7.干掉n最右侧的1
n&(n-1) (n-1)将最右侧1的右边的数全变成相反数
///191.位1的个数
///338.比特位计数
///461.汉明距离
- 位运算能加括号加括号,减少优先级判断错误
- 异或运算
- a^0 =a
- a^a=0
- a^b^c = a^(b^c)
///136.只出现一次的数字
///260.只出现一次的数字III
6.FloodFill算法:
数对的赋值技巧:
bfs(广度优先遍历): 借助队列和pair,队列中记录的是需要修改元素的坐标,然后满足题目条件需要修改的元素就往队列中插入。
坐标上下左右移动技巧:
int bx[4] = {0,0,-1,1};
int by[4] = {-1,1,0,0};
这两个数组可以来实现坐标点的上下移动,来查找周围可以入队列的点。
另一种方式就是递归这样就程序看起来简便:
Vis只是一个表示标记遍历过元素的下标的数组,并没有实际意义,这样就不需要标记更改原数组的元素来标记已访问。
用bfs求最边权为1(不管那个方向每走一步距离相等)短路径问题:
首先把起始点全部放在一个队列中,然后将当前队列中的元素一次往外扩散。
最小基因突变问题:433. 最小基因变化 - 力扣(LeetCode)
这类题可以转变成最短路问题的原因:
这个题中基因突变的最终形式和基因种类以及每次突变基因的个数是一定的。
多源bfs:将多个满足筛选对象的元素直接当成一个整体依次插入到队列中,然后通过两个循环来出入队列中的元素,第一层循环统计的是往外扩展的次数,第二层循环(内循环)表示每一层满足筛选条件的元素,也就是每往外扩展一层要出入队的元素。
动态规划:
1、状态变量描述:dp数组中存放的数值
2、状态方程:找dp数组中的递推公式
3、初始化:初始化地推开始的值
4、填表并边界处理:依次计算在dp中存入初始化值后面的值
5、空间优化:如果只和n的前几项有关那么就不需要创建dp数组直接用几个变量即可
求出数值过大一般取模