• 打表技巧和矩阵处理技巧


    打表找规律应用场景

    1. 某个面试题,输入参数类型简单,并且只有一个实际参数。
    2. 要求的返回值类型也简单,并且只有一个
    3. 用暴力方法,把输入参数对应的返回值,打印出来看看,进而优化代码。

    1.打表技巧实际案例

    案例一:

            小虎去买苹果,商店只提供两种类型的塑料袋,每种类型都有任意数量。1.能装下6个苹果的袋子,2.能装下8个苹果的袋子。小虎可以自由使用两种袋子来装苹果,但是小虎有强迫症,他要求自己使用的袋子数量必须最少,且使用的每个袋子必须装满。给定一个正整数N,返回至少使用多少袋子。如果N无法让使用的每个袋子必须装满,返回-1。

    1. public class AppleMinBags {
    2. public static int minBags(int apple) {
    3. if (apple < 0) {
    4. return -1;
    5. }
    6. int bag8 = (apple >> 3);
    7. int rest = apple - (bag8 << 3);
    8. while(bag8 >= 0) {
    9. // rest 个
    10. if(rest % 6 ==0) {
    11. return bag8 + (rest / 6);
    12. } else {
    13. bag8--;
    14. rest += 8;
    15. }
    16. }
    17. return -1;
    18. }
    19. public static int minBagAwesome(int apple) {
    20. if ((apple & 1) != 0) { // 如果是奇数,返回-1
    21. return -1;
    22. }
    23. if (apple < 18) {
    24. return apple == 0 ?
    25. 0 : (apple == 6 || apple == 8) ?
    26. 1: (apple == 12 || apple == 14 || apple == 16) ?
    27. 2 : -1;
    28. }
    29. return (apple - 18) / 8 + 3;
    30. }
    31. public static void main(String[] args) {
    32. for(int apple = 1; apple < 200;apple++) {
    33. System.out.println(apple + " : "+ minBags(apple));
    34. }
    35. }
    36. }

    案例二:

            给定一个正整数N,表示有N份青草统一堆放在仓库里。有一只牛和一只羊,牛先吃,羊后吃,它俩轮流吃草。不管是牛还是羊,每一轮能吃的草量必须是:1,4,16,64…(4的某次方)。谁最先把草吃完,谁获胜。假设牛和羊都绝顶聪明,都想赢,都会做出理性的决定。根据唯一的参数N,返回谁会赢。

    1. public class EatGrass {
    2. // 如果n份草,最终先手赢,返回"先手"
    3. // 如果n份草,最终后手赢,返回"后手"
    4. public static String winner1(int n) {
    5. //0 1 2 3 4
    6. //后 先 后 先 先
    7. if (n < 5) {
    8. return (n == 0 || n == 2) ? "后手" : "先手";
    9. }
    10. int base = 1;
    11. while (base <= n) {
    12. if (winner1(n - base).equals("后手")) {
    13. return "先手";
    14. }
    15. if (base > n / 4) { // 防止base*4之后溢出
    16. break;
    17. }
    18. base *= 4;
    19. }
    20. return "后手";
    21. }
    22. public static String winner2(int n) {
    23. if (n % 5 == 0 || n % 5 == 2) {
    24. return "后手";
    25. } else {
    26. return "先手";
    27. }
    28. }
    29. public static void main(String[] args) {
    30. for (int i = 0; i <= 50; i++) {
    31. System.out.println(i + " : " + whoWin(i));
    32. }
    33. }
    34. }

    案例三:

            对于一个正整数x(3≤x≤1000),寻找一种方案,将x分解成连续正整数的和。即x=x1+x2+…+xn。其中x1、x2、…、xn是自小至大的连续正整数,且n>1。
            比如,对于输入的数字10,可以分解成"10=1+2+3+4"。
            如果存在多于一种的可行方案,则选取等式右边项的个数最多的那一种。比如,9可以分解为"9=2+3+4",也可以分解为"9=4+5"。但是前一种分解成3个数的和,后一种分解成2个数的和,所以前一种是有效解。

    1. public class MSumToN {
    2. public static boolean isMSum1(int num) {
    3. for (int start = 1; start <= num; start++) {
    4. int sum = start;
    5. for (int j = start + 1; j <= num; j++) {
    6. if (sum + j > num) {
    7. break;
    8. }
    9. if (sum + j == num) {
    10. return true;
    11. }
    12. sum += j;
    13. }
    14. }
    15. return false;
    16. }
    17. public static boolean isMSum2(int num) {
    18. //判断num是不是2的某次方 ==0是2的某次方 !=0不是2的某次方
    19. //十进制8的二进制表示为
    20. // 00001000 减去1后二进制形式为00000111 与原来二进制数字与操作后结果为0
    21. //再例如十进制10二进制表示为 00001010 减去1后二进制表示为00001001
    22. //00001010 & 00001001 = 00001000 不为0
    23. if (num < 3) {
    24. return false;
    25. }
    26. return (num & (num - 1)) != 0;
    27. }
    28. public static void main(String[] args) {
    29. for (int num = 1; num < 200; num++) {
    30. System.out.println(num + " : " + isMSum1(num));
    31. }
    32. // System.out.println("test begin");
    33. // for (int num = 1; num < 5000; num++) {
    34. // if (isMSum1(num) != isMSum2(num)) {
    35. // System.out.println("Oops!");
    36. // }
    37. // }
    38. // System.out.println("test end");
    39. }
    40. }

    2.矩阵处理实际案例

    案例一:zigzag打印矩阵。

            给定一个正方形或者长方形矩阵matrix,实现zigzag打印。[[0,1,2],[3,4,5],[6,7,8]]的打印顺序是0,1,3,6,4,2,5,7,8。

    1. public class ZigZagPrintMatrix {
    2. public static void printMatrixZigZag(int[][] matrix) {
    3. int Ar = 0;
    4. int Ac = 0;
    5. int Br = 0;
    6. int Bc = 0;
    7. int Endr = matrix.length - 1;
    8. int Endc = matrix[0].length - 1;
    9. boolean fromUp = false;//是不是从右上向左下打印
    10. while (Ar != Endr + 1) {
    11. printLevel(matrix, Ar, Ac, Br, Bc, fromUp);
    12. Ar = Ac == Endc ? Ar + 1 : Ar;
    13. Ac = Ac == Endc ? Ac : Ac + 1;
    14. Bc = Br == Endr ? Bc + 1 : Bc;
    15. Br = Br == Endr ? Br : Br + 1;
    16. fromUp = !fromUp;
    17. }
    18. System.out.println();
    19. }
    20. public static void printLevel(int[][] m,
    21. int tR, int tC, int dR, int dC, boolean f) {
    22. if (f) {
    23. while (tR != dR + 1) {
    24. System.out.print(m[tR++][tC--] + " ");
    25. }
    26. } else {
    27. while (dR != tR - 1) {
    28. System.out.print(m[dR--][dC++] + " ");
    29. }
    30. }
    31. }
    32. public static void main(String[] args) {
    33. int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
    34. printMatrixZigZag(matrix);
    35. }
    36. }

    案例二:转圈打印矩阵

            给定一个整型矩阵matrix,请按照顺时针转圈的方式打印它。
    输入[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
    返回值[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]

    1. public class PrintMatrixSpiralOrder {
    2. public static void spiralOrderPrint(int[][] matrix) {
    3. int tR = 0;
    4. int tC = 0;
    5. int dR = matrix.length - 1;
    6. int dC = matrix[0].length - 1;
    7. while (tR <= dR && tC <= dC) {
    8. printEdge(matrix, tR++, tC++, dR--, dC--);
    9. }
    10. }
    11. public static void printEdge(int[][] m,
    12. int a, int b, int c, int d) {
    13. if (a == c) {
    14. for (int i = b; i <= d; i++) {
    15. System.out.print(m[a][i] + " ");
    16. }
    17. } else if (b == d) {
    18. for (int i = a; i <= c; i++) {
    19. System.out.print(m[i][b] + " ");
    20. }
    21. } else {
    22. int curC = b;
    23. int curR = a;
    24. while (curC != d) {
    25. System.out.print(m[a][curC] + " ");
    26. curC++;
    27. }
    28. while (curR != c) {
    29. System.out.print(m[curR][d] + " ");
    30. curR++;
    31. }
    32. while (curC != b) {
    33. System.out.print(m[c][curC] + " ");
    34. curC--;
    35. }
    36. while (curR != a) {
    37. System.out.print(m[curR][b] + " ");
    38. curR--;
    39. }
    40. }
    41. }
    42. public static void main(String[] args) {
    43. int[][] matrix = {
    44. { 1, 2, 3, 4 },
    45. { 5, 6, 7, 8 },
    46. { 9, 10, 11, 12 },
    47. { 13, 14, 15, 16 } };
    48. spiralOrderPrint(matrix);
    49. }
    50. }

    案例三:原地旋转正方形矩阵

            给定一个正方形矩阵matrix,原地调整成顺时针90度转动的样子。[[a,b,c],[d,e,f],[g,h,i]]变成[[g,d,a],[h,e,b],[i,f,c]]。

    1. public class RotateMatrix {
    2. public static void rotate(int[][] matrix) {
    3. int a = 0;
    4. int b = 0;
    5. int c = matrix.length - 1;
    6. int d = matrix[0].length - 1;
    7. while (a < c) {
    8. rotateEdge(matrix, a++, b++, c--, d--);
    9. }
    10. }
    11. public static void rotateEdge(int[][] m,
    12. int a, int b, int c, int d) {
    13. int tmp = 0;
    14. for (int i = 0; i < d - b; i++) {
    15. tmp = m[a][b + i];
    16. m[a][b + i] = m[c - i][b];
    17. m[c - i][b] = m[c][d - i];
    18. m[c][d - i] = m[a + i][d];
    19. m[a + i][d] = tmp;
    20. }
    21. }
    22. public static void printMatrix(int[][] matrix) {
    23. for (int i = 0; i != matrix.length; i++) {
    24. for (int j = 0; j != matrix[0].length; j++) {
    25. System.out.print(matrix[i][j] + " ");
    26. }
    27. System.out.println();
    28. }
    29. }
    30. public static void main(String[] args) {
    31. int[][] matrix = {
    32. { 1, 2, 3, 4 },
    33. { 5, 6, 7, 8 },
    34. { 9, 10, 11, 12 },
    35. { 13, 14, 15, 16 } };
    36. printMatrix(matrix);
    37. rotate(matrix);
    38. System.out.println("=========");
    39. printMatrix(matrix);
    40. }
    41. }

  • 相关阅读:
    windows10安装其他版本cuda环境
    数据结构与算法之美10(排序)
    简明 SQL 子查询指南:掌握 EXISTS 实现数据筛选
    深入多线程锁
    VSCode中Java程序入口的数据输入流的常用形式
    Python学习之CSDN21天学习挑战赛计划之4
    自定义过滤器配置 Shiro 认证失败返回 json 数据
    嵌入式单片机无刷电机FOC控制与实现详解
    Express 路由
    面试 | Python 自动化测试技术面试真题
  • 原文地址:https://blog.csdn.net/z1171127310/article/details/127415372