常用算法
来源:互联网 发布:影楼行业全国数据 编辑:程序博客网 时间:2024/05/29 07:59
最大子序列之和
明白一件事,只要加了之后数为正,这个肯定在最大子序列里面,如果是小于0,那么就会出现最大子序列有可能在其里面,也有可能在未执行的子串中。
public static int maxSum(int arr[]){ int maxSum = 0,curSum = 0; for(int i=0;i<arr.length;i++){ curSum += arr[i]; if(curSum>maxSum){ maxSum = curSum; } if(curSum<0){ curSum = 0; } } return maxSum;}
最长公共子序列
最长公共子序列,不连续String str1 = “abcdef”;和String str2 = “abefcb”;最长公共子序列为abef。利用动态规划解决LCS问题,用二维数组记录LCS的长度,一次递归到最小的子问题。
c[i,j] = 0 i=0 or j=0c[i,j] = c[i-1,j-1] + 1 i,j>0 and Xi = Yic[i,j] = max(c[i,j-1],c[i-1,j]) i,j>0 and Xi!=Yi
// 假如返回两个字符串的最长公共子序列的长度 ,数组右下角元素就是LCS的长度
public static int[][] LCS(String str1, String str2) { int[][] arr = new int[str1.length() + 1][str2.length() + 1];//建立二维矩阵 // 初始化边界条件 for (int i = 0; i <= str1.length(); i++) { arr[i][0] = 0;//每行第一列置零 } for (int j = 0; j <= str2.length(); j++) { arr[0][j] = 0;//每列第一行置零 } // 填充矩阵 for (int i = 1; i <= str1.length(); i++) { for (int j = 1; j <= str2.length(); j++) { if (str1.charAt(i - 1) == str2.charAt(j - 1)) { arr[i][j] = arr[i - 1][j - 1] + 1; } else { arr[i][j] = (arr[i - 1][j] >= arr[i][j - 1] ? arr[i - 1][j] : arr[i][j - 1]); } } } return matrix; }
要是我们需要打印出最长的子序列呢,我们将上面的函数的出来的二维数组进行分析。按照三个dp公式来递归
0 0 0 0 0 0 0
0 1 1 1 1 1 1
0 1 2 2 2 2 2
0 1 2 2 2 3 3
0 1 2 2 2 3 3
0 1 2 3 3 3 3
0 1 2 3 4 4 4
public static void print(int[][] opt, String X, String Y, int i, int j) { if (i == 0 || j == 0) { return; } if (X.charAt(i - 1) == Y.charAt(j - 1)) { print(opt, X, Y, i - 1, j - 1); System.out.print(X.charAt(i - 1)); } else if (opt[i - 1][j] >= opt[i][j]) { print(opt, X, Y, i - 1, j); } else { print(opt, X, Y, i, j - 1); } }
最长公共子串
public static int[][] LCS(String str1,String str2){ int max = 0; char[] a = str1.toCharArray(); char[] b = str2.toCharArray(); int [][] c = new int[a.length+1][b.length+1]; for(int i=1;i<=a.length;i++){ for(int j=1;j<=b.length;j++){ if(a[i-1]==b[j-1]){ c[i][j] = c[i-1][j-1]+1; }else{ c[i][j] = 0; } max = Math.max(max, c[i][j]); } } return c; }
最小栈的实现
思路参考于http://blog.jobbole.com/106940/
实现一个栈,带有出栈,入栈,取最小元素三个方法,要保证三个方法的时间复杂度都是O(1)
思路一:
创建一个整型变量min,初始值为-1,
当第一个元素入栈的时候,min为0,把唯一元素值当做做小的元素。
之后每一个新元素入栈,让新元素和min指向位置的元素比较,根据大小判断是否交换坐标
当调用getMin的时候,直接返min所指向的位置的元素就行
这个方法对三种要求都是时间和空间都为O(1),但是我们取出一个最小值后呢,就没有人来顶替他了,所以一个下标来记录最小值是不可取的。
优化方法:
新建一个栈设为B,原来的栈设为A。
当第一个元素进入栈A的时候,让新元素的下标进入B,这个唯一的元素是栈A的当前最小值
每当新的元素进入栈A的时候,比较新元素和栈A当前的最小值的大小,如果小于栈A当前的最小值,则让新元素进入B,此时B栈顶的元素就是栈A的最小值。
每当有栈A出栈的时候,如果出栈元素是栈A当前最小值,则让栈B的栈顶元素也出栈,此时栈B指向的是原来栈A的第二小元素,也是此刻最小的元素
调用getMin方法的时候,直接返回栈B的栈顶所指向的栈A的对应元素。
判断2的乘方
思路参考伯乐在线
二的乘方有个特点就是二进制全是1,那么1与0相与为0,也就是说假设N为二的乘方,那么N&N-1,结果必然是0,也就是说我们返回N&N-1是不是等于0,就可以知道这个数是不是2的乘方。
找出缺失的整数
一个无序数组里有99个不重复的正整数,范围从1到100,唯独少了一个整数,如何找出?
解法:用1到100的和减去原来有缺的1到100的整数和,得出的结果就是缺失的整数。
一个无序数组有若干个整数,范围1到100,其中99个数都出现了偶数次,只有一个整数出现了奇数次,如何找出来?
遍历整个数组,做异或运算,相同为0不同为1,所以偶数次都会被抵消为0,只有出现为奇数次的就会被留下
一个无序数组有若干个整数,范围1到100,其中99个数都出现了偶数次,只有两个个整数出现了奇数次,如何找出来?
依旧做异或运算,最终的结果就是这两个数异或的结果,但是这样两个数还是照不出来多少啊,我们先对异或的结果进行二进制分析,如果异或出来的是101,那么说明这两个数转为二进制后一个尾数是0,一个是1,那么我们可以根据二进制尾数为0的进行异或,可以找一个,同理,为1的可以找一个。当然尾数为0也可以处理,肯定异或出来的数有某一位为1,按照某一位进行分而治之,就可以解决。
辗转相除法
定律:(a>b)a与b的最大公约数等于a除以b的余数c和b之间的自大公约数。
public static int gcd(int a,int b){ int c = a+b; if(a<b){ a = c-a; b = c-b; } if(a%b==0){ return b; }else{ return gcd(b,a%b); }}
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- 常用算法
- LeetCode-93-Restore IP Addresses 暴力
- poj 3421 X-factor Chains
- Codeforces 858F ( Codeforces Round #434 Div. 2 F ) Wizard's Tour 图论dfs
- 蓝桥杯 算法提高 数字黑洞
- Hadoop Yarn初探
- 常用算法
- 第五周项目2
- 简单模拟——LRC才不会告诉你们的事情
- 位图显示和图形界面技术(操作系统桌面显示技术)
- JavaScript 事件入门
- php中json_decode()和json_encode()的使用方法
- Java集合---ConcurrentHashMap原理分析
- T-SQL查询进阶--详解公用表表达式(CTE)
- JAVA集合体系