public static void hanoi(int i){ process(i,"左","右","中"); } public static void process(int i, String from,String to,String other){ if (i == 1){ System.out.println("1 "+from +"->"+to); } else { process(i - 1,from,other,to); System.out.println(i+from +"->"+to); process(i-1,other,to,from); } }
/** * @Author: 郜宇博 * @Date: 2021/11/9 14:04 */ public class PrintString { public static void main(String[] args) { printAllSubsquence("abc"); } public static void printAllSubsquence(String str) { char[] chs = str.toCharArray(); process(chs, 0); } /** * 对于每一个i步,都存在走和不走的选择 */ public static void process(char[] chars,int i){ if (i == chars.length){ System.out.println(String.valueOf(chars)); } else { //走字符i process(chars,i+1); char temp = chars[i]; chars[i] = 0; //不走字符i process(chars,i+1); chars[i] = temp; } } }
public static ArrayList allPermutations(String str){ ArrayList<String> strings = new ArrayList<>(); process(str.toCharArray(),0,strings); return strings; } public static void process(char[] chars,int i, ArrayList<String> res){ //base if (i == chars.length){ res.add(String.valueOf(chars)); } //对于[0- i-1]的char数组,已经是选择过得了,后面的i-end随意选择一个进行全排列 else { boolean[] visit = new boolean[26]; for (int j = i ; j < chars.length; j++){ if ( ! visit[chars[j]-'a']){ visit[chars[j]-'a'] = true; swap(chars,i,j); process(chars,i+1,res); swap(chars,i,j); } } } } public static void swap(char[] chars,int i, int j){ char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; }
给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸 牌,规定玩家A先拿,玩家B后拿,但是每个玩家每次只能拿走最左或最右的纸牌,玩家A 和玩家B都绝顶聪明。请返回最后获胜者的分数。
/** * @Author: 郜宇博 * @Date: 2021/11/9 14:54 */ //先手拿牌 public static int firstTake(int []nums,int left,int right){ //只有一个牌,先手拿到了 if (left == right){ return nums[left]; } //拿左边 = 左边值+ 后手拿牌 //右边= //然后选择一个最大的 int valueTakeLeft = nums[left] + lastTake(nums,left+1,right); int valueTakeRight = nums[right] + lastTake(nums,left,right-1); return Math.max(valueTakeLeft,valueTakeRight); } //后手拿牌 public static int lastTake(int []nums,int left,int right){ if (left == right){ return 0; } //此时牌少一个 int valueTakeLeft = firstTake(nums,left+1,right); int valueTakeRight = firstTake(nums,left,right-1); //先手的人知道我有这两个选择了,因此先手人的选择是让我选这两个里最小 return Math.min(valueTakeLeft,valueTakeRight); } public static int winner(int []nums){ if (nums == null || nums.length == 0){ return 0; } int AfirstValue = firstTake(nums,0,nums.length-1); int BlastValue = lastTake(nums,0,nums.length-1); return Math.max(AfirstValue,BlastValue); }
/** * @Author: 郜宇博 * @Date: 2021/11/9 15:31 */ public class ReverseStackNoOtherSpace { public static void main(String[] args) { Stack<Integer> s = new Stack<>(); s.push(1); s.push(2); reverseStack(s); for (Integer num: s){ System.out.print(num); } } public static int popBottom(Stack<Integer> stack){ //保留栈顶元素值 int res = stack.pop(); //不为空 if (!stack.isEmpty()){ //一直尝试得到last int last = popBottom(stack); //得到last后,将保留的元素压入栈中 stack.push(res); return last; } else { return res; } } public static void reverseStack(Stack<Integer> stack){ int bottom = popBottom(stack); if (!stack.isEmpty()){ reverseStack(stack); } stack.push(bottom); } }
规定1和A对应、2和B对应、3和C对应... 那么一个数字字符串比如"111",就可以转化为"AAA"、"KA"和"AK"。 给定一个只有数字字符组成的字符串str,返回有多少种转化结果。
/** * @Author: 郜宇博 * @Date: 2021/11/9 16:25 */ public class ToLetterCounts { public static void main(String[] args) { System.out.println(convertLetter("12131")); } /** * 从左往右尝试 */ public static int convertLetter(String str){ if (str == null || str.length() == 0) { return 0; } int process = process(str.toCharArray(), 0); return process; } /** * 获取i及其后面字符的转化可能数 */ public static int process(char[] chars,int i){ if (i == chars.length){ return 1; } if (chars[i] == '0'){ return 0; } if (chars[i] == '1'){ //获取i+1及其后的可能数 int res = process(chars,i+1); //1和任何个位数都可以组成一个字母 if (i+1 < chars.length){ //获取i+2及其后的可能数 res += process(chars,i+2); } return res; } if (chars[i] == '2'){ int res = process(chars,i+1); //小于26的数才能转字母 if (i+1 < chars.length && chars[i+1] <='6' && chars[i+1]>='0'){ res += process(chars,i+2); } return res; } //3开始 else { //获取之后的 return process(chars,i+1); } } }
给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表 i号物品的重量和价值。
给定一个正数bag,表示一个载重bag的袋子,你装的物 品不能超过这个重量。返回你能装下最多的价值是多少?
/** * @Author: 郜宇博 * @Date: 2021/11/9 16:56 */ public class MaxValueBag { public static void main(String[] args) { int[] weights = { 3, 2, 4, 7 }; int[] values = { 5, 6, 3, 19 }; int bag = 11; System.out.println(bagProblem(weights, values, bag)); } public static int process(int[] weight,int []value,int i,int bag,int selectWeight){ if (i == weight.length){ return 0; } if (selectWeight > bag){ return 0; } int select = process(weight,value,i+1,bag,selectWeight+weight[i]) + value[i]; int unSelect = process(weight,value,i+1,bag,selectWeight); return Math.max(select,unSelect); } public static int bagProblem(int [] weight,int[] value,int bag){ int process = process(weight, value, 0, bag, 0); return process; } }
/** * @Author: 郜宇博 * @Date: 2021/11/9 17:12 */ public class Queen { public static void main(String[] args) { long n1 = System.currentTimeMillis(); System.out.println(queen(13)); System.out.println(System.currentTimeMillis()-n1); long n2 = System.currentTimeMillis(); System.out.println(queen1(13)); System.out.println(System.currentTimeMillis()-n2); } public static int queen(int n){ int[] record = new int[n]; return process(record,0,n); } /** * 得出i及其以后的行的可能数 */ public static int process(int[] record,int i, int n){ int res = 0; //base case if (i == n){ return 1; } else { //每一列查看 for (int j = 0; j < n; j++){ if (isValid(record,i,j)){ record[i] = j; res += process(record, i+1,n); } } } return res; } public static int queen1(int n){ if (n < 1 || n > 32){ return 0; } int limit = n == 32? -1:(1 << n)-1; return process1(limit,0,0,0); } /** * 不再使用record进行记录,而是使用二进制限制 * 有三个限制:列限制,左斜线限制,右斜线限制,全部异或就是总限制 * 只需要在下一行尝试的时候在非限制的地方尝试就可以了; */ public static int process1(int limit,int colLim,int leftSlash,int rightSlash){ //base case,如果所有列都放满了 if (colLim == limit){ return 1; } //总共可放的位置 int pos = 0; //最右边可放的位置,一个尝试 int mostRightPos = 0; int res = 0; pos = limit & (~ ( colLim | leftSlash | rightSlash)); while (pos!= 0){ mostRightPos = pos & (~pos + 1); pos = pos - mostRightPos; //列限制 = 之前的列限制 | 选择的位置 res += process1(limit,colLim|mostRightPos, //固定:左限制 = 之前的左限制 | 选择的位置 ,在左移一位 (leftSlash|mostRightPos) <<1, //固定:右限制 = 之前的右限制 | 选择的位置 ,在右移一位,高位补齐0 (rightSlash | mostRightPos) >>>1 ); } return res; } public static boolean isValid(int[] record,int i, int j){ for (int k = 0; k < i; k++){ if (record[k] == j || Math.abs(record[k]-j) == Math.abs(i-k)){ return false; } } return true; } }