9.1 背包问题: 给定两个长度为n的数组weight和values,weight[i]和values[i]分别代表i号物品的重量和价值,给定一个载重为正数的袋子bag,最多能装的价值为多少
按理来说应该是没有问题的,但是代码跑出来是有问题的代码跑出来是有问题的
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] weights = {3, 2, 4, 7};
int[] values = {5, 6, 3, 19};
int bag = 11;
int k = process(weights,values,0,bag,0);
}
public static int process(int[] weights,int[] values,int i,int bag,int alreadyWeight) {
if (alreadyWeight > bag) {
return 0;
}
if (i == weights.length) {
return 0;
}
int k = Math.max(process(weights,values,i+1,bag,alreadyWeight),
values[i]+process(weights,values,i+1,bag,alreadyWeight+weights[i]));
return k;
}
}
以下形式是没有问题的
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] weights = {3, 2, 4, 7};
int[] values = {5, 6, 3, 19};
int bag = 11;
int k = process(weights,values,0,bag,0);
}
public static int process(int[] weights,int[] values,int i,int bag,int alreadyWeight) {
if (i == weights.length) {
return 0;
}
int no = process(weights,values,i+1,bag,alreadyWeight);
/* !!! 这里最关键 !!! */
/* !!! 上面那样写是错误的写法 !!! */
if (alreadyWeight+weights[i] > bag) {
return 0;
}
int yes = values[i]+process(weights,values,i+1,bag,alreadyWeight+weights[i]);
return Math.max(no, yes);
}
}
9.1 给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿。但是每个玩家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪,请返回最后获胜者的分数。
其实这个要靠记住了,想想出来的可能性不大
public class CardsInLine {
public static int win1(int[] arr) {
if (arr == null || arr.length == 0) return 0;
// 返回先手或者后手的最大值
return Math.max(f(arr,0,arr.length-1), s(arr,0,arr.length-1));
}
// 先手
public static int f(int[] arr,int L,int R) {
if (L == R) return arr[L];
return Math.max(arr[L]+s(arr,L+1,R),arr[R]+s(arr,L,R-1));
}
// 后手
public static int s(int[] arr,int L,int R) {
if (L == R) return 0;
// 后手就是先手的最小值,范围确定好
return Math.min(f(arr,L+1,R),f(arr,L,R-1));
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {1,2,100,4};
System.out.println(win1(arr));
}
}
9.3 给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数,如何实现
就是每一次递归都拿到栈底的值,直到栈为null后开始回调,将拿到的栈底的值依次插入栈中
public class ReverseStack {
public static void reverse(Stack<Integer> stack) {
if (stack.isEmpty()) return;
int i = f(stack);
reverse(stack);
stack.push(i);
}
// 拿到栈底的值
public static int f(Stack<Integer> stack) {
int result = stack.pop();
if (stack.isEmpty()) {
return result;
}
else {
int last = f(stack);
stack.push(result);
return last;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Stack<Integer> stack = new Stack<>();
stack.add(1); stack.add(2); stack.add(3); stack.add(4); stack.add(5);
reverse(stack);
String s = stack.toString();
System.out.println(s);
}
}
9.4 规定1和A对应、2和B对应、3和C对应…,那么一个数字字符串比如“111”,就可以转换为“AAA”、“KA”和“AK”。给定一个只有数字字符组成的字符串str,返回有多少种转换结果。
假设从i位置开始,i位置之前的字符是转换好的,那么
如果i位置的字符为0的话那么就返回0,因为没有办法转换了,
如果i位置的字符为1的话,可以分为两种情况,自己转换,递归i+1,和加上后一个字符转换,递归i+2,
如果i位置的字符为2的话,可以像1一样去转换,但是后一个字符不能超过6,因为超过6就没办法转换了
public class TransformationStr {
public static int process(char[] str,int i) {
if (i == str.length) {
return 1;
}
if (str[i] == '0') {
return 0;
}
if (str[i] == '1') {
int res = process(str,i+1);
if (i+1 < str.length) {
res += process(str,i+2);
}
return res;
}
if (str[i] == '2') {
int res = process(str,i+1);
if (i+1 < str.length && (str[i+1] >= '0' && str[i+1] <= '6') ) {
res += process(str,i+2);
}
return res;
}
return process(str,i+1);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String s = "7210231231232031203123";
char[] str = s.toCharArray();
System.out.println(process(str,0));
}
}