1.猜密码(排列组合问题 —- 回溯)
    // 都是数字,都不重复 // 给出范围、最小数字数量?? // 可能的组合:1、数字在范围内的;2、数字和字母分别递增排序;3、每个数字数量大于最小数字数量;4、空返回None // 按字典序输出

    1. // 同:类似洗扑克牌解法,在n张里抽
    2. function guessNum(arr, minRange) {
    3. // 边界:重复、空、范围不够
    4. if (arr.length < minRange || Array.from(new Set(arr)).length !== arr.length) {
    5. return;
    6. }
    7. if (!arr) return "None";
    8. // 思路:遍历删n个元素,递归到单次目标范围,剩余数组sort
    9. let res = [];
    10. // 1、从最小数字范围开始
    11. for (let range = minRange; range < arr.length; range++) {
    12. // 1-1、要删去多少个元素
    13. let diff = arr.length - range;
    14. // 1-2、遍历删去所有可能组合
    15. for (let j = 0; j < arr.length; j++) {
    16. let restArr = iterator(arr, diff, j);
    17. // 2、对剩余数组,按递增排序后,得到单次有效组合,加入结果
    18. res.push(restArr.sort((a, b) => a - b));
    19. }
    20. // 1-3、递归组合
    21. function iterator(arr, diff, j) {
    22. // 完成目标范围的递归,返回组合后的数组
    23. if (!diff) return arr;
    24. // 深拷贝数组
    25. let cloneArr = [...arr];
    26. // 删除单个元素后
    27. cloneArr.splice(j, 1);
    28. return iterator(cloneArr, diff--);
    29. }
    30. }
    31. // 3、结果按字典序排序输出
    32. // 规律:长度同,比较前n个最小的
    33. // 前面是从最小范围开始,得到的res数组里的元素长度是由小到大的
    34. // 递归组合是按由小到大组合去删去某个元素,得到的剩余数组应该是由大到小
    35. // 那么在长度变化的一段起切片,翻转数组后再拼接即可
    36. for (let k = 0; k < res.length - 1; k++) {
    37. // 长度变化
    38. if (res[k].length !== res[k+1].length) {
    39. // 切片后拼接
    40. let cutArr = res.splice(0,k+1).reverse()
    41. res = cutArr.concat(...res)
    42. }
    43. }
    44. return res;
    45. }

    2.跳格子游戏

    1. 地上共有N个格子,你需要跳完地上所有的格子,但是格子间是有强依赖关系的,跳完前一个格子后,后续的格子才会被开启,格子间的依赖关系由多组steps数组给出,steps[0]表示前一个格子,steps[1]表示steps[0]可以开启的格子:
    2. 比如[0,1]表示从跳完第0个格子以后第1个格子就开启了,比如[2,1],[2,3]表示跳完第2个格子后第1个格子和第3个格子就被开启了
    3. 请你计算是否能由给出的steps数组跳完所有的格子,如果可以输出yes,否则输出no
    4. 说明:
    5. 1.你可以从一个格子跳到任意一个开启的格子
    6. 2.没有前置依赖条件的格子默认就是开启的
    7. 3.如果总数是N,则所有的格子编号为[0,1,2,3....N-1]连续的数组
    8. 输入描述:
    9. 输入一个整数N表示总共有多少个格子,接着输入多组二维数组steps表示所有格子之间的依赖关系
    10. 输出描述:
    11. 如果能按照steps给定的依赖顺序跳完所有的格子输出yes
    12. 否则输出no
    13. 示例1
    14. 输入
    15. 3
    16. 0 1
    17. 0 2
    18. 输出
    19. yes
    20. 说明
    21. 总共有三个格子[0,1,2],跳完0个格子后第1个格子就开启了,跳到第0个格子后第2个格子也被开启了,按照0->1->2或者0->2->1的顺序都可以跳完所有的格子
    22. 示例2
    23. 输入
    24. 2
    25. 1 0
    26. 0 1
    27. 输出
    28. no
    29. 说明
    30. 总共有2个格子,第1个格子可以开启第0格子,但是第1个格子又需要第0个格子才能开启,相互依赖,因此无法完成
    31. 示例3
    32. 输入
    33. 6
    34. 0 1
    35. 0 2
    36. 0 3
    37. 0 4
    38. 0 5
    39. 输出
    40. yes
    41. 说明
    42. 总共有6个格子,第0个格子可以开启第1,2,3,4,5个格子,所以跳完第0个格子之后其他格子都被开启了,之后按任何顺序可以跳完剩余的格子
    43. 示例4
    44. 输入
    45. 5
    46. 4 3
    47. 0 4
    48. 2 1
    49. 3 2
    50. 输出
    51. yes
    52. 说明
    53. 跳完第0个格子可以开启格子4,跳完格子4可以开启格子3,跳完格子3可以开启格子2,跳完格子2可以开启格子1,按照0->4->3->2->1这样就跳完所有的格子
    54. 示例5
    55. 输入
    56. 4
    57. 1 2
    58. 1 0
    59. 输出
    60. yes
    61. 说明
    62. 总共4个格子[0,1,2,3],格子1和格子3没有前置条件所以默认开启,格子1可以开启格子0和格子2,所以跳到格子1之后就可以开启所有的格子,因此可以跳完所有格子
    63. 备注:
    64. 1 <= N <500
    65. steps[i].length=2
    66. 0<=step[i][0],step[i][1]<N

    3.欢乐的周末
    小华和小为是很要好的朋友,他们约定周末一起吃饭。通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达),求小华和小为都能到达的聚餐地点有多少个?
    输入描述:

    第一行输入m和n,m代表地图的长度,n代表地图的宽度。

    第二行开始具体输入地图信息,地图信息包含:

    0 为通畅的道路

    1 为障碍物(且仅1为障碍物)

    2 为小华或者小为,地图中必定有且仅有2个 (非障碍物)

    3 为被选中的聚餐地点(非障碍物)

    输出描述:

    可以被两方都到达的聚餐地点数量,行末无空格。

    示例1

    输入:

    4 4

    2 1 0 3

    0 1 2 1

    0 3 0 0

    0 0 0 0

    输出:

    2

    说明:

    第一行输入地图的长宽为3和4。

    第二行开始为具体的地图,其中:3代表小华和小明选择的聚餐地点;2代表小华或者小明(确保有2个);0代表可以通行的位置;1代表不可以通行的位置。此时两者能都能到达的聚餐位置有2处

    示例2

    输入:

    4 4

    2 1 2 3

    0 1 0 0

    0 1 0 0

    0 1 0 0

    输出:

    0

    说明:

    第一行输入地图的长宽为4和4。

    第二行开始为具体的地图,其中:3代表小华和小明选择的聚餐地点;2代表小华或者小明(确保有2个);0代表可以通行的位置;1代表不可以通行的位置。由于图中小华和小为之间有个阻隔,此时,没有两人都能到达的聚餐地址,故而返回0

    备注:

    地图的长宽为m和n,其中:

    4 <= m <= 100

    4 <= n <= 100

    聚餐的地点数量为 k,则

    1< k <= 100

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. import java.util.Scanner;
    4. public class Main{
    5. public static int endX; //餐厅横坐标
    6. public static int endY; //餐厅纵坐标
    7. public static void main(String[] args) {
    8. Scanner sc = new Scanner(System.in);
    9. int lenX = sc.nextInt();
    10. int lenY = sc.nextInt();
    11. int[][] migong = new int[lenX][lenY]; //迷宫数组
    12. List<int[]> hw = new ArrayList<>(); //小华和小为的坐标
    13. List<int[]> canGuan = new ArrayList<>(); //餐厅的坐标
    14. for ( int i=0; i<lenX; i++) {
    15. for ( int j=0; j<lenY; j++) {
    16. migong[i][j] = sc.nextInt();
    17. if (migong[i][j] == 2) {
    18. int[] h = { i, j};
    19. hw.add(h);
    20. } else if (migong[i][j] == 3) {
    21. int[] c = { i, j};
    22. canGuan.add(c);
    23. }
    24. }
    25. }
    26. int[] xh = hw.get(0); //小华的位置坐标
    27. int[] xw = hw.get(1); //小为的位置坐标
    28. int res = 0;
    29. for (int i=0;i<canGuan.size();i++) {
    30. int temp[][] = copy(migong); //复制原数组(否则会导致数组改变)
    31. endX = canGuan.get(i)[0]; //餐馆横坐标
    32. endY = canGuan.get(i)[1]; //餐馆纵坐标
    33. if ( forEnd(xh[0],xh[1],temp) == 1 ) {
    34. temp = copy(migong);
    35. if ( forEnd(xw[0],xw[1],temp) == 1 ) {
    36. res++;
    37. }
    38. }
    39. }
    40. System.out.println(res);
    41. }
    42. public static int[][] copy(int[][] nums){
    43. int x = nums.length;
    44. int y = nums[0].length;
    45. int[][] res = new int[x][y];
    46. for ( int i=0; i<x; i++) {
    47. for ( int j=0; j<y; j++) {
    48. res[i][j] = nums[i][j];
    49. }
    50. }
    51. return res;
    52. }
    53. public static int forEnd(int x,int y,int[][] ints){
    54. int U = x - 1; //向上
    55. int D = x + 1; //向下
    56. int L = y - 1; //向左
    57. int R = y + 1; //向右
    58. if(x==endX && y==endY){ //到达餐馆返回1
    59. return 1;
    60. }
    61. if (U>=0) { //边界处理
    62. if (ints[U][y] != 1) { //只要非1都能通过
    63. ints[x][y] = 1; //能通过则本格置为1,表示已经走过
    64. if (forEnd(U,y,ints)==1) { //递归处理,若值为1表示可以到达直接return 1
    65. return 1;
    66. }
    67. }
    68. }
    69. if (D<ints.length) {
    70. if (ints[D][y] != 1) {
    71. ints[x][y] = 1;
    72. if (forEnd(D,y,ints)==1) {
    73. return 1;
    74. }
    75. }
    76. }
    77. if (L>=0) {
    78. if (ints[x][L] !=1 ) {
    79. ints[x][y] = 1;
    80. if (forEnd(x,L,ints)==1) {
    81. return 1;
    82. }
    83. }
    84. }
    85. if (R<ints[0].length) {
    86. if (ints[x][R] != 1) {
    87. ints[x][y] = 1;
    88. if (forEnd(x,R,ints)==1) {
    89. return 1;
    90. }
    91. }
    92. }
    93. return 0;
    94. }
    95. }

    4.解压报文 —- leetcode 394
    为了提升数据传输的效率,会对传输的报文进行压缩处理。输入一个压缩后的报文,请返回它解压后的原始报文。
    压缩规则:n[str],表示方括号内部的 str 正好重复 n 次。注意 n 为正整数(0 < n <= 100),str只包含小写英文字母,不考虑异常情况。

    1. const decodeString = (s) => {
    2. let numStack = []; // 存倍数的栈
    3. let strStack = []; // 存 待拼接的str 的栈
    4. let num = 0; // 倍数的“搬运工”
    5. let result = ''; // 字符串的“搬运工”
    6. for (const char of s) { // 逐字符扫描
    7. if (!isNaN(char)) { // 遇到数字
    8. num = num * 10 + Number(char); // 算出倍数
    9. } else if (char == '[') { // 遇到 [
    10. strStack.push(result); // result串入栈
    11. result = ''; // 入栈后清零
    12. numStack.push(num); // 倍数num进入栈等待
    13. num = 0; // 入栈后清零
    14. } else if (char == ']') { // 遇到 ],两个栈的栈顶出栈
    15. let repeatTimes = numStack.pop(); // 获取拷贝次数
    16. result = strStack.pop() + result.repeat(repeatTimes); // 构建子串
    17. } else {
    18. result += char; // 遇到字母,追加给result串
    19. }
    20. }
    21. return result;
    22. };