赞
踩
此篇是本人 LeetCode 算法刷题技巧总结,还包括刷过的算法题分类,自己记录以便后续二刷三刷,也分享给大家欢迎一起交流探讨。话说现在非常遗憾大学期间没能坚持搞 ACM,出来社会才越发觉得后悔,但是遗憾归遗憾,我还是相信种一棵树是十年前,其次是现在,所以重新再来为时不晚!刷起!!!
小技巧
暴力
能解决绝大部分算法题,但纯暴力往往都会超时,要学会剪枝。双指针法
,前后指针
(左右夹逼),快慢指针
。升维
:空间换时间。所有算法都是找重复性
,机器的世界很简单(不像人心),基本上只会 if...else...
、for
、while
、recursion
,也就是它只会做重复的事,重复做事正好也是它所擅长的。实战
小技巧
链表
:比较简单直接,多写。最近相关性
的话,可以尝试用栈解决。单调(递增/递减)栈
,算法中比较常用,算法模板类似如下:stack<int> st;
// 此处一般需要给数组最后添加结束标志符
for (遍历这个数组)
{
while (栈不为空 && 栈顶元素小于当前元素)
{
栈顶元素出栈;
更新结果;
}
当前数据入栈;
}
实战
小技巧
递归不慢
,傻递归才慢,要想不傻,剪枝!或缓存中间结果。分而治之
,利用递归将大问题拆成小问题,直到最终子问题,逐步返回子问题结果,直到解决最初的问题。不合适就退回上一步
,同时将数据状态也回到上一步。深度优先搜索
,递归的一种,利用栈做回退,找所有解,或者遍历所有情况中途剪枝(遍所有)。广度优先搜索
,递归的一种,一般利用队列,找最近或者最优解(遍部分)。void recursion(level, param1, param2, ...) { // 递归终结条件 if (level > MAX_LEVEL) { // 处理结果 return; } // 处理当前层逻辑 process(...) // 递归到下一层 recursion(level + 1, ...) // 清理当前层 }
实战
小技巧
子问题的最优解能递推到最终问题的最优解
。这种子问题最优解称为最优子结构。贪心
:当下做局部最优判断回溯
:能够回退动态规划
:最优判断 + 回退实战
好文参考:我作了首诗,保你闭着眼睛也能写对二分查找
小技巧
单调递增或者单调递减或者局部单调
)上下界
索引访问
二分查找很容易,但是极易出错
。 int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return result or break;
} else if(nums[mid] < target) {
l = mid + 1;
} else {
r = mid -1;
}
}
实战
小技巧
实战
小技巧
每个父节点最多只有26个子节点
)。典型的应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。class Trie { private Trie[] children; private final Integer R = 26; private boolean end; Trie() { children = new Trie[R]; } public void insert(String word) { Trie node = this; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); int index = c - 'a'; if (node.children[index] == null) { node.children[index] = new Trie(); } node = node.children[index]; } node.end = true; } public boolean search(String word) { Trie node = this.searchWith(word); return node != null && node.end; } public boolean startsWith(String word) { Trie node = this.searchWith(word); return node != null; } private Trie searchWith(String word) { Trie node = this; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); int index = c - 'a'; if (node.children[index] != null) { node = node.children[index]; } else { return null; } } return node; } }
实战
小技巧
private class UnionFind { /** * 连通分量的个数 */ private int count; private int[] parent; public int getCount() { return count; } /* * 一开始各个节点都是指向自己 */ public UnionFind(int n) { this.count = n; parent = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } } /* * 查询根节点 */ private int find(int x) { while (x != parent[x]) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; } /* * 合并节点 */ public void union(int x, int y) { int xRoot = find(x); int yRoot = find(y); if (xRoot == yRoot) { return; } parent[xRoot] = yRoot; count--; } }
实战
任何节点左右子树高度差不超过 1
,通过旋转来进行平衡
任何节点左右子树高度差小于 2 倍
。它满足以下条件:
判断m是否是奇数:(m & 1) == 1 // 奇数,或者除2余数不为0:m % 2 != 0
x除以2:x >> 1 // mid = (left + right) / 2 --> mid = (left + right) >> 1
清零x最低位的1:x = x & (x - 1) // 10010 -> 10000 、0001000 -> 0000000
得到x最低位为1的x:x = x & -x
将x最右边的n位清零:x & (~0 << n)
获取x的第n位值:(x >> n) & 1
获取x的第n位的幂值:x & (1 << (n-1))
将第n位设为1:x | (1 << n)
将第n位设为0:x & (~(1 << n))
将x最高位至第n位(含)清零:x & ((1 << n) - 1)
将第n位至第0位(含)清零:x & (~((1 << (n + 1))-1))
数组排序:Arrays.sort(nums) // 对nums数组排序
数组填充:Arrays.fill(chars, '-') // 将chars数组全部填充为"-"
数组Copy:Arrays.copyOfRange(chars, 0, 10) // 复制chars中0(包含)-10(不包含)位为一个新数组
翻转字符串:new StringBuilder(strTmp).reverse().toString() // 将strTmp字符串翻转
拼接字符串:String.join(".", tmp) // 用"."拼接tmp(Iterable子类)中的数据为一个串
字符型数字转成Integer数字:减字符0 // 例如'5' - '0' 会等于 5
未完待续...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。