算法-技巧
1.回文子串(动态规划)
- P(i,j)=(P(i+1,j−1)&&S[i]==S[j])
- 如果 S[i+1,j-1]S[i+1,j−1] 是回文串,那么只要 S[ i ]S[i] == $S[ j ] $,就可以确定 S[i,j]S[i,j]也是回文串了。
-
求 长度为 11 和长度为 22 的 P(i,j)P(i,j) 时不能用上边的公式,因为我们代入公式后会遇到 P[i][j]P[i][j] 中 i > j 的情况,比如求 P[1][2]P[1][2] 的话,我们需要知道 P[1+1][2-1]=P[2][1]P[1+1][2−1]=P[2][1] ,而 P[2][1]P[2][1] 代表着 S[2,1]S[2,1] 是不是回文串,显然是不对的,所以我们需要单独判断。
2.数字技巧
- 掌握 / 和 % 可以解决很多问题,例如数学12整数转罗马文字
- 2200 / 1000 == 2 相除得到整数结果,余数忽略
- 2200 % 1000 == 200 取余忽略整除结果,只取余数
- char型数组转 int,char - ‘0’
3.数组中的数字操作
应该想到指针! 多指针操作
4.动态规划思路
二维数组,计算两点的路径数量总和的问题,动态方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]
5.深度优先遍历
如果需要进行上下层级之间的比较,每次处理一个节点就好,左右节点递归处理
6.回溯模板代码
回溯不可重复
/**
* 回溯算法不可重复 相当于每一层选择一个进行排列组合
* in: 1 2 3
* out: [1]
* [1, 2]
* [1, 2, 3]
* [1, 3]
* [2]
* [2, 3]
* [3]
*/
public void backtrack(int[] nums , int index , Stack<Integer> temp){
for(int i = index; i < nums.length; i++){
temp.push(nums[i]);
backtrack(nums,i + 1 , temp);
temp.pop();
}
}
回溯可重复
/**
* 回溯算法重复 相当于每一层都有nums.length 个选择 进行排列组合
* in:1 2
* out:[1, 1, 1]
* [1, 1, 2]
* [1, 2, 1]
* [1, 2, 2]
* [2, 1, 1]
* [2, 1, 2]
* [2, 2, 1]
* [2, 2, 2]
*
*/
public void backtrack_CF(int[] nums , Stack<Integer> temp){
if(temp.size() >= 3){
System.out.println(temp);
return;
}
for(int i = 0; i < nums.length; i++){
temp.push(nums[i]);
backtrack_CF(nums,temp);
temp.pop();
}
}
7.子序问题 ==> 都可以用动态规划来解决
最大连续子序和:dp(i)=max(dp(i-1)+array[i],array[i])
/** * 推导公式 : dp(i)=max(dp(i-1)+array[i],array[i]) */ private int MaxCountOf(int[] array){ //max就是上面的dp[i] int max = array[0]; //因为这个dp[i]老是变,所以比如你dp[4]是8 dp[5]就变成-7了,所以需要res保存一下 int res = array[0]; for (int i = 1; i < array.length; i++) { max = Math.max(max + array[i], array[i]); res = Math.max(res, max); } return res; }
最长递增子序:dp[i] = max(dp[i], dp[j] + 1) for j in [0, i)。
public int lengthOfLIS(int[] nums) { if (nums.length == 0) return 0; int[] dp = new int[nums.length]; int res = 0; Arrays.fill(dp,1); for (int i=0;i<nums.length;i++){ for (int j=0;j<i;j++){ if (nums[i]>nums[j]) dp[i] = Math.max(dp[i],dp[j]+1); } res = Math.max(res,dp[i]); } return res; }
最长公共子序:
(1) 如果S的最后一位等于T的最后一位,则最大子序列就是{s1,s2,s3...si-1}和{t1,t2,t3...tj-1}的最大子序列+1
(2) 如果S的最后一位不等于T的最后一位,那么最大子序列就是
① {s1,s2,s3..si}和 {t1,t2,t3...tj-1} 最大子序列
② {s1,s2,s3...si-1}和{t1,t2,t3....tj} 最大子序列
public int longestCommonSubsequence(String text1, String text2) { char[] s1 = text1.toCharArray(); char[] s2 = text2.toCharArray(); int[][] dp = new int[s1.length+1][s2.length+1]; for (int i=1;i<s1.length+1;i++){ for (int j=1;j<s2.length+1;j++){ if (s1[i-1] == s2[j-1]){//最后一位相同 dp[i][j] = dp[i-1][j-1] +1; }else{//最后一位不同 dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]); } } } return dp[s1.length][s2.length]; }
8.字母的任意组合问题
dpi=dp(i−1)+dp(i−2)
9.位运算
X&1 是取X二进制的最低以为
X>>1 向右移1位
位运算 x & (x-1) 将最低位的1置为0
如果n是2的幂次方 则 : n & (n - 1) == 0
大小写转换 a ^ (1<<5) 可以实现大小写转换

浙公网安备 33010602011771号