回溯法
? 通常在二维矩阵上找路径这类问题都可以应用回溯法解决。
动态规划
如果面试题是求一个问题的最优解(通常是求最大值或者最小值),而且该问题能够分解成若干个子问题,并且子问题之间哈游重叠的更小子问题,就可以考虑用动态规划来解决这个问题。动态规划的四个特点:
? 求一个问题的最优解
? 整体问题的最优解是依赖各个子问题的最优解
? 把大问题分解成若干个小问题,这些小问题之间还有相互重叠的更小问题
? 从上往下分析问题,从下往上求解问题。由于子问题在分解大问题的过程中重复出现,为了避免重复求解子问题,我们可以用从下往上的顺序先计算小问题的最优解并存储下来,再以此为基础求
取大问题的最优解。
剪绳子
package Chapter2;
public class CutString {
//动态规划
public int maxProductAfterCutting_solution1(int length) {
if(length < 2)
return 0;
if(length == 2)
return 1;
if(length == 3)
return 2;
int[] products = new int[length+1];
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;
int max = 0;
for(int i = 4; i<=length; i++){
max = 0;
for(int j = 1; j<=i/2; j++){
int product = products[j] * products[i-j];
if(product > max)
max = product;
}
products[i] = max;
}
return products[length];
}
//贪婪法
public int maxProductAfterCutting_solution2(int length) {
if(length < 2)
return 0;
if(length == 2)
return 1;
if(length == 3)
return 2;
int timeOf3 = length/3;
if(length - timeOf3*3 == 1)
timeOf3 -= 1;
int timeOf2 = (length-timeOf3*3)/2;
return (int)Math.pow(3, timeOf3)*(int)Math.pow(2,timeOf2);
}
/**
* @param args
*/
public static void main(String[] args) {
CutString cs = new CutString();
int length = 41;
System.out.println(cs.maxProductAfterCutting_solution1(length));
System.out.println(cs.maxProductAfterCutting_solution2(length));
}
}
位运算
二进制的位运算一共有五种:与、或、异或、左移和右移。
? 左移运算符m<<n表示把m左移n位。在左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0。比如:
00001010<<2 = 00101000
10001010<<3 = 01010000
把数左移一位相当于乘以2,左移两位相当于乘以4,一次类推左移n位相当于将m乘以pow(2,n)。在实际编程中应尽可能的用移位运算代替乘除法。
? 右移运算符m>>n表示把m右移n位。在右移n位的时候,最右边的n位将被丢弃。但右移时处理最左边位的情形要稍微复杂一点。如果数字是一个无符号数值,则用0填补最左边的n位:如果数字是一个有符号数值,则用数字的符号位填补最左边的n位。也就是说,如果数字原先是要给正数,则右移之后在最左边补n个0;如果数字原先是负数,则右移之后在最左边补n个1。下面是对两个8位有符号数进行右移的例子:
00001010>>2 = 00000010
10001010>>3 = 11110001