目录
给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数。
规定1和A对应、2和B对应、3和C对应…26和Z对应,那么一个数字字符串比如"111”就可以转化为:“AAA”、“KA"和"AK”。给定一个只有数字字符组成的字符串str,请问有多少种转化结果?
【汉诺塔问题】:![](https://img-blog.csdnimg.cn/7fb0059f555247d19e2467777a2b9149.png)
/**
* @ProjectName: study3
* @FileName: TowerOfHanoi
* @author:HWJ
* @Data: 2023/6/12 10:09
*/
public class TowerOfHanoi {
public static void main(String[] args) {
int n = 3;
hanoi(3);
}
public static void hanoi(int n){
if (n > 0){
func(n, "左", "右", "中");
}
}
public static void func(int i, String start, String end, String other){
if (i == 1){
System.out.println("Move " + i + " from " + start + " to " + end);
} else {
func(i-1, start, other, end);
System.out.println("Move " + i + " from " + start + " to " + end);
func(i-1, other, end, start);
}
}
}
【打印字符串子序列: (包括空字符串)】
import java.util.ArrayList;
import java.util.List;
/**
* @ProjectName: study3
* @FileName: PrintAllSubsquences
* @author:HWJ
* @Data: 2023/6/12 10:28
*/
public class PrintAllSubsquences {
public static void main(String[] args) {
String str = "abc";
function(str);
System.out.println("---------------------");
printAll(str);
}
public static void function(String str){
char[] charArray = str.toCharArray();
process(charArray, 0, new ArrayList<>());
}
public static void process(char[] chars, int i, List<Character> res){
if (i == chars.length){
printList(res);
}else {
List<Character> have = copyList(res);
have.add(chars[i]);
process(chars, i+1, have); // 要当前字符
List<Character> notHave = copyList(res);
process(chars, i+1, notHave); // 不要当前字符
}
}
public static void printList(List<Character> res){
for (char c :res) {
System.out.print(c);
}
System.out.println();
}
public static List<Character> copyList(List<Character> res){
ArrayList<Character> list = new ArrayList<>(res);
return list;
}
//-----------------------------------------------------------------------------------
// 方法二
public static void printAll(String str){
char[] charArray = str.toCharArray();
process(charArray, 0);
}
public static void process(char[] chars, int i){
if (i == chars.length){
System.out.println(String.valueOf(chars));
return;
}
process(chars, i+1); // 要当前字符的路
char tmp = chars[i];
chars[i] = 0;
process(chars, i+1); // 不要当前字符的路
chars[i] = tmp;
}
}
【打印字符串的全部排列: (不能出现重复的排列)】
import java.util.ArrayList;
import java.util.List;
/**
* @ProjectName: study3
* @FileName: PrintAllPermutations
* @author:HWJ
* @Data: 2023/6/12 11:06
*/
public class PrintAllPermutations {
public static void main(String[] args) {
String str = "aabc";
printALl(str);
}
public static void printALl(String str) {
char[] charArray = str.toCharArray();
ArrayList<String> res = new ArrayList<>(); // 用res来记录所有全排列结果
process(charArray, 0, res);
printList(res);
}
public static void process(char[] chars, int i, ArrayList<String> res) {
if (i == chars.length) {
res.add(String.valueOf(chars));
return;
}
/**
* boolean[] bools = new boolean[26];
* if (!bools[chars[j] - 'a']){
* // 加入这个的含义是一个字符串中 可能有多个相同的字符,他们交换到同一个位置的作用是一样的
* // 可能会造成全排列的重复
* bools[chars[j] - 'a'] = true;
* swap(chars, i, j);
* process(chars, i+1, res); // 当找到一个全排列后,要重新交换,使数组还原,已使下一次得到正确的全排列
* swap(chars, i, j);
* }
*/
boolean[] bools = new boolean[26];
for (int j = i; j < chars.length; j++) {
if (!bools[chars[j] - 'a']) {
bools[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 tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
}
public static void printList(List<String> res){
for (String c :res) {
System.out.println(c);
}
}
}
给定一个整型数组arr,代表数值不同的纸牌排成一条线
玩家A和玩家B依次拿走每张纸牌
规定玩家A先拿,玩家B后拿
但是每个玩家每次只能拿走最左或最右的纸牌
玩家A和玩家B都绝顶聪明
请返回最后获胜者的分数
/**
* @ProjectName: study3
* @FileName: Win
* @author:HWJ
* @Data: 2023/6/12 12:38
*/
public class Win {
public static void main(String[] args) {
int[] arr = {1,2,100,4};
System.out.println(win(arr));
}
public static int win(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){ // 如果是最后一张排,因为是后手,就无法拿到这张牌,返回0
return 0;
}
// 返回对手已经拿了一张牌
// 此时我们便变为后手,
// 因为对面先手,一定会拿对自己有利的牌,我们就无法拿到有利的牌,所以我们只能拿到最小的牌中对自己有利的牌
return Math.min(f(arr, l+1, r), f(arr, l, r-1));
}
}
给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数。
import java.util.Stack;
/**
* @ProjectName: study3
* @FileName: ReverseStack
* @author:HWJ
* @Data: 2023/6/12 13:01
*/
public class ReverseStack {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>(); // 堆栈是后进先出,如果没有逆序,应打印 5 4 3 2 1
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
while (!stack.isEmpty()){
System.out.println(stack.pop());
}
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
reverse(stack);
System.out.println("----------reverse---------");
while (!stack.isEmpty()){
System.out.println(stack.pop());
}
}
public static void reverse(Stack<Integer> stack){
if (stack.isEmpty()){
return;
}
int res = remove(stack);
reverse(stack);
stack.push(res);
}
// 移除一个栈中的最后一个元素,其他的栈元素整体往下移
public static int remove(Stack<Integer> stack){
int res = stack.pop();
if (stack.isEmpty()){
return res;
}else {
int last = remove(stack);
stack.push(res);
return last;
}
}
}
规定1和A对应、2和B对应、3和C对应…26和Z对应,那么一个数字字符串比如"111”就可以转化为:“AAA”、“KA"和"AK”。给定一个只有数字字符组成的字符串str,请问有多少种转化结果?
/**
* @ProjectName: study3
* @FileName: NumToStr
* @author:HWJ
* @Data: 2023/6/12 14:31
*/
public class NumToStr {
public static void main(String[] args) {
}
public static int translate(String str){
char[] charArray = str.toCharArray();
return process(charArray, 0);
}
public static int process(char[] str, int i){
if ( i == str.length){ // 如果已经把所有的都决定完了,返回1
return 1;
}
if (str[i] == '0'){ // 如果第i位为0,没法转换,返回0
return 0;
}
if (str[i] == '1'){
int res = process(str, i+1); // i 自己作为单独的部分,后续有多少种方法,
if (i+1 < str.length){
res += process(str, i+2);// (i 和 i+1) 自己作为单独的部分,后续有多少种方法
}
return res;
}
if (str[i] == '2'){
int res = process(str, i+1); // i 自己作为单独的部分,后续有多少种方法,
if (i+1 < str.length && str[i+1] >= '0' && str[i+1] <= '6'){ // (i 和 i+1) 自己作为单独的部分,后续有多少种方法,
res += process(str, i+2); // 明确要求其不能超过26
}
return res;
}
return process(str, i+1);
}
}
给定两个长度都为N的数组weights和values,weights[i]和values[i] 分别表示 i 号 物品的 重量和 价值。给定一个正数bag,表示一个载重为bag的袋子,你装的的物品不能超过这个重量。
返回你能装下的的最大价值是多少?
从左往右依次考虑每个商品要还是不要,然后就得到了所有情况,再不断递归找最大。
/**
* @ProjectName: study3
* @FileName: getMaxValue
* @author:HWJ
* @Data: 2023/6/12 14:52
*/
public class getMaxValue {
public static void main(String[] args) {
}
public static int search(int[] weights, int[] values, int bag){
//return process(weights, values, 0, 0, 0,bag);
return process2(weights, values, 0,0,bag);
}
public static int process(int[] weights, int[] values, int i, int alreadyWeight, int alreadyValue, int bag){
// 方法和下一个类似, 但下一个更好
if (i == weights.length){
return alreadyValue;
}
if (alreadyWeight > bag){
return 0;
}
return Math.max(
process(weights, values, i+1, alreadyWeight, alreadyValue, bag),
process(weights, values, i+1, alreadyWeight+weights[i], alreadyValue+values[i], bag)
);
}
public static int process2(int[] weights, int[] values, int i, int alreadyWeight, int bag){
if (i == weights.length){
return 0;
}
if (alreadyWeight > bag){
return 0;
}
return Math.max(
process2(weights, values, i+1, alreadyWeight, bag), // 不要这个商品
values[i] + process2(weights, values, i+1, alreadyWeight+weights[i], bag) //要这个商品,
// 不断递归,相当于依次对所有商品进行了要和不要两种的考虑,然后再依次找最大。
);
}
}
// 暴力递归时的原则:找到可变参数形式最简单,可变参数个数最少的方法