一个IT小菜鸟不断整理遇到的算法之路~~~~~
如果你有什么常见的好的算法,欢迎评论区留言~~~
问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
可分为多个相关子问题,子问题的解被重复使用
递归地定义最优解的代价
自底向上地计算优化解的代价保存之,并获取构造最优解的信息
根据构造最优解的信息构造优化解
把原始问题划分成一系列子问题;
求解每个子问题仅一次,并将其结果保存在一个表中,以后用到时直接存取,不重复计算,节省计算时间
自底向上地计算。
整体问题最优解取决于子问题的最优解(状态转移方程)(将子问题称为状态,最终状态的求解归结为其他状态的求解)
LeetCode JAVA解题—300. 最长上升子序列详见方法一
LeetCode-322 零钱兑换
面试题 17.16. 按摩师
198. 打家劫舍
213. 打家劫舍 II
337. 打家劫舍 III(树形动态规划)
887. 鸡蛋掉落
贪心算法
超详细讲解队列&栈知识点汇总干货(附带例题+代码)
有关树的递归965. 单值二叉树
面试题13. 机器人的运动范围
5366. 检查网格中是否存在有效路径(dfs)
辗转相除法gcd
思路:一般处理链表中间节点问题,两个指针 slow 与 fast 一起遍历链表。slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。
876. 链表的中间结点
KMP算法的Next数组详解
JAVA正则表达式语法示例与语法大全
java中Arrays.sort()的几种用法
自定义sort函数排序规则:
一般来讲,sort默认是增序排列
如果想要降序排列: words为数组
Arrays.sort(words, (s1, s2) -> s2.length() - s1.length());
937. 重新排列日志文件
字典树又名前缀树,Trie树,是一种存储大量字符串的树形数据结构,相比于HashMap存储,在存储单词(和语种无关,任意语言都可以)的场景上,节省了大量的内存空间。
典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计
它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
字典树
820. 单词的压缩编码
相信大家经常会遇到关于括号的算法题目
这类题目还是有点难度的
一般涉及括号的题目建议想一想用栈来解答
1111. 有效括号的嵌套深度
1021. 删除最外层的括号
32.最长有效括号 这道题目难度是困难,但代码很简单,思路很好,强烈建议
编辑距离算法被数据科学家广泛应用,是用作机器翻译和语音识别评价标准的基本算法。
最直观的方法是暴力检查所有可能的编辑方法,取最短的一个。所有可能的编辑方法达到指数级,但我们不需要进行这么多计算,因为我们只需要找到距离最短的序列而不是所有可能的序列。
编辑距离及编辑距离算法
72. 编辑距离
计算机原码,反码,补码
1009. 十进制整数的反码
1022. 从根到叶的二进制数之和
超详细讲解二叉树知识点干货汇总——概念、遍历+代码(递归、非递归)+递归解题
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。
最简单的判断回文串:
public static boolean check(String str){
if(null == str || "".equals(str)){
return false
}
int i = 0;
int j = str.length() - 1;
String[] strings = str.split("");
boolean flag = false;
for (; i <= j; i++,j--) {
if(!strings[i].equals(strings[j])){
return false;
}
}
return true;
}
但一般的不会考这么简单,下面整理了一下相关回文串的题
最长回文子串(强烈推荐官方题解视频中的第三种方法动态规划,简单高效,马拉车算法(Manacher)量力而行)
*算了算了,忍耐不住还是想把第三种方法写出来,哈哈哈~~~~*
思路:动态规划
1.先判别子串两边界的字符是否相同
2.若相同则继续判别中间的子串是否相同
3.相同则true,不同为false
状态: d p [ i ] [ j ] dp[i][j] dp[i][j]表示子串 s [ i . . j ] s[i..j] s[i..j]是否为回文子串
状态转移方程:
d p [ i ] [ j ] = ( s [ i ] = = s [ j ] ) a n d d p [ i + 1 ] [ j − 1 ] dp[i][j]=(s[i] == s[j]) and dp[i+1][j-1] dp[i][j]=(s[i]==s[j]) and dp[i+1][j−1]
边界条件:解释当 s [ i . . j ] s[i..j] s[i..j]的长度为2或3的时候不必检查子串是否回文
例如: aba 、aa
j − 1 − ( i + 1 ) + 1 < 2 , 整 理 得 j − i < 3 j-1-(i+1)+1<2,整理得j-i<3 j−1−(i+1)+1<2,整理得j−i<3
初始化:
dp[i][i]=true //显然单个字符是回文串
输出:
在得到一个状态的值为true的时候 , 记录起始位置和长度,填表完成以后截取
如果你还是不明白,看到下面例子一定就恍然大悟了:
字符 | b | a | b | a | b |
---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 |
状态转移方程:
d p [ i ] [ j ] = ( s [ i ] = = s [ j ] ) dp[i][j]=(s[i] == s[j]) dp[i][j]=(s[i]==s[j]) and
( ( j − 1 < 3 ) o r d p [ i + 1 ] [ j − 1 ] ) ((j-1<3) or dp[i+1][j-1]) ((j−1<3) or dp[i+1][j−1])
由于dp[i][j]参考它左下方的值:
(1)先升序填列
(2)再升序填行
列为子串右边界,行为左边界
可以看到(0,4)的值取决于(1,3)and (s[i] == s[j])
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | T | F | T | F | T |
1 | T | F | T | F | |
2 | T | F | T | ||
3 | T | F | |||
4 | T |
public class Solutions{
public String longestPalindrome(String s){
int len = s.length();
if(len <2){
return s;
}
int maxlen=1;
int begin =0;
// dp[i][j]表示子串s[i..j]是否为回文子串
boolean [][] dp=new boolean[len][len];
for(int i=0;i<len;++i){
dp[i][i]=true;
}
char[] charArray=s.toCharArray();
for(int j=1;j<len;++j){
for(int i=0;i<j;i++){
if (charArray[i] != charArray[j]){
dp[i][j]=false;
}else{
if (j-i<3){
dp[i][j]=ture;
}else{
dp[i][j]==dp[i+1][j-1];
}
}
//只要dp[i][j]==true成立,就表示子串s[i..j]是回文,此时记录回文长度和起始位置
if(dp[i][j] && j-i+1>maxlen){
maxlen=j-i+1;
begin=i;
}
}
}
return s.substring(begin,begin+maxlen);
}
}
验证回文串(大小写字母等同且含有数字)
分割会汶川大地震