• 【算法训练营】 - 打表技巧和矩阵处理技巧


    【算法训练营】 - 打表技巧和矩阵处理技巧

    https://www.bilibili.com/video/BV1Ef4y1T7Qi
    https://github.com/algorithmzuo

    打表法

    1. 问题如果返回值不太多,可以用hardcode的方式列出,作为程序的一部分
    2. 一个大问题解决时底层频繁使用规模不大的小问题的解,如果小问题的返回值满足条件1),可以把小问题的解列成一张表,作为程序的一部分
    3. 打表找规律(本节课重点),有关1)和2)内容欢迎关注后序课程

    题目一

    小虎去买苹果,商店只提供两种类型的塑料袋.每种类型都有任意数量。

    1. 能装下6个苹果的袋子
    2. 能装下8个苹果的袋子

    小虎可以自由使用两种袋子来装苹果,但是小虎有强迫症,他要求自己使用的袋子数量必须最少,且使用的每个袋子必须装满。
    给定一个正整数N,返回至少使用多少袋子。如果N无法让使用的每个袋子必须装满,返回-1

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

    题目二

    package class38;
    
    public class Code02_EatGrass {
    
    	// 如果n份草,最终先手赢,返回"先手"
    	// 如果n份草,最终后手赢,返回"后手"
    	public static String whoWin(int n) {
    		if (n < 5) {
    			return n == 0 || n == 2 ? "后手" : "先手";
    		}
    		// 进到这个过程里来,当前的先手,先选
    		int want = 1;
    		while (want <= n) {
    			if (whoWin(n - want).equals("后手")) {
    				return "先手";
    			}
    			if (want <= (n / 4)) {
    				want *= 4;
    			} else {
    				break;
    			}
    		}
    		return "后手";
    	}
    
    	public static String winner1(int n) {
    		if (n < 5) {
    			return (n == 0 || n == 2) ? "后手" : "先手";
    		}
    		int base = 1;
    		while (base <= n) {
    			if (winner1(n - base).equals("后手")) {
    				return "先手";
    			}
    			if (base > n / 4) { // 防止base*4之后溢出
    				break;
    			}
    			base *= 4;
    		}
    		return "后手";
    	}
    
    	public static String winner2(int n) {
    		if (n % 5 == 0 || n % 5 == 2) {
    			return "后手";
    		} else {
    			return "先手";
    		}
    	}
    
    	public static void main(String[] args) {
    		for (int i = 0; i <= 50; i++) {
    			System.out.println(i + " : " + whoWin(i));
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    题目三

    定义一种数:可以表示成若干(数量>1)连续正数和的数比如:
    5 =2+3,5就是这样的数
    12= 3+4+5,12就是这样的数
    1 不是这样的数,因为要求数量大于1个、连续正数和
    2 = 1 +1,2也不是,因为等号右边不是连续正数
    给定一个参数N,返回是不是可以表示成若干连续正数和的数

    package class38;
    
    public class Code03_MSumToN {
    
    	public static boolean isMSum1(int num) {
    		for (int start = 1; start <= num; start++) {
    			int sum = start;
    			for (int j = start + 1; j <= num; j++) {
    				if (sum + j > num) {
    					break;
    				}
    				if (sum + j == num) {
    					return true;
    				}
    				sum += j;
    			}
    		}
    		return false;
    	}
    
    	public static boolean isMSum2(int num) {
    //		
    //		return num == (num & (~num + 1));
    //		
    //		return num == (num & (-num));
    //		
    //		
    		return (num & (num - 1)) != 0;
    	}
    
    	public static void main(String[] args) {
    		for (int num = 1; num < 200; num++) {
    			System.out.println(num + " : " + isMSum1(num));
    		}
    		System.out.println("test begin");
    		for (int num = 1; num < 5000; num++) {
    			if (isMSum1(num) != isMSum2(num)) {
    				System.out.println("Oops!");
    			}
    		}
    		System.out.println("test end");
    
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    矩阵处理技巧

    矩阵特殊轨迹问题
    核心技巧:思想不要限制在局部坐标的变化上,要找到coding上的宏观调度

    1. zigzag打印矩阵
    package class40;
    
    public class Code07_ZigZagPrintMatrix {
    
    	public static void printMatrixZigZag(int[][] matrix) {
    		int tR = 0;
    		int tC = 0;
    		int dR = 0;
    		int dC = 0;
    		int endR = matrix.length - 1;
    		int endC = matrix[0].length - 1;
    		boolean fromUp = false;
    		while (tR != endR + 1) {
    			printLevel(matrix, tR, tC, dR, dC, fromUp);
    			tR = tC == endC ? tR + 1 : tR;
    			tC = tC == endC ? tC : tC + 1;
    			dC = dR == endR ? dC + 1 : dC;
    			dR = dR == endR ? dR : dR + 1;
    			fromUp = !fromUp;
    		}
    		System.out.println();
    	}
    
    	public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f) {
    		if (f) {
    			while (tR != dR + 1) {
    				System.out.print(m[tR++][tC--] + " ");
    			}
    		} else {
    			while (dR != tR - 1) {
    				System.out.print(m[dR--][dC++] + " ");
    			}
    		}
    	}
    
    	public static void main(String[] args) {
    		int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
    		printMatrixZigZag(matrix);
    
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    1. 转圈打印矩阵
    package class40;
    
    public class Code05_PrintMatrixSpiralOrder {
    
    	public static void spiralOrderPrint(int[][] matrix) {
    		int tR = 0;
    		int tC = 0;
    		int dR = matrix.length - 1;
    		int dC = matrix[0].length - 1;
    		while (tR <= dR && tC <= dC) {
    			printEdge(matrix, tR++, tC++, dR--, dC--);
    		}
    	}
    
    	public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
    		if (tR == dR) {
    			for (int i = tC; i <= dC; i++) {
    				System.out.print(m[tR][i] + " ");
    			}
    		} else if (tC == dC) {
    			for (int i = tR; i <= dR; i++) {
    				System.out.print(m[i][tC] + " ");
    			}
    		} else {
    			int curC = tC;
    			int curR = tR;
    			while (curC != dC) {
    				System.out.print(m[tR][curC] + " ");
    				curC++;
    			}
    			while (curR != dR) {
    				System.out.print(m[curR][dC] + " ");
    				curR++;
    			}
    			while (curC != tC) {
    				System.out.print(m[dR][curC] + " ");
    				curC--;
    			}
    			while (curR != tR) {
    				System.out.print(m[curR][tC] + " ");
    				curR--;
    			}
    		}
    	}
    
    	public static void main(String[] args) {
    		int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
    				{ 13, 14, 15, 16 } };
    		spiralOrderPrint(matrix);
    
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    1. 原地旋转正方形矩阵
    package class40;
    
    public class Code06_RotateMatrix {
    
    	public static void rotate(int[][] matrix) {
    		int a = 0;
    		int b = 0;
    		int c = matrix.length - 1;
    		int d = matrix[0].length - 1;
    		while (a < c) {
    			rotateEdge(matrix, a++, b++, c--, d--);
    		}
    	}
    
    	public static void rotateEdge(int[][] m, int a, int b, int c, int d) {
    		int tmp = 0;
    		for (int i = 0; i < d - b; i++) {
    			tmp = m[a][b + i];
    			m[a][b + i] = m[c - i][b];
    			m[c - i][b] = m[c][d - i];
    			m[c][d - i] = m[a + i][d];
    			m[a + i][d] = tmp;
    		}
    	}
    
    	public static void printMatrix(int[][] matrix) {
    		for (int i = 0; i != matrix.length; i++) {
    			for (int j = 0; j != matrix[0].length; j++) {
    				System.out.print(matrix[i][j] + " ");
    			}
    			System.out.println();
    		}
    	}
    
    	public static void main(String[] args) {
    		int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } };
    		printMatrix(matrix);
    		rotate(matrix);
    		System.out.println("=========");
    		printMatrix(matrix);
    
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    spring-statemachine 状态机自定义持久化入库
    MyEclipse数据库工具使用教程:使用 SQL
    Java教程之自己动手编写清理工具:如何清理MarkDown文档中多余的图片
    一文理解分布式开发中的服务治理
    elasticsearch
    堡垒机有录像吗?好用吗?有什么作用?
    透过Redis源码探究字符串的实现
    Unigui中获取手机特征码
    docker-compose的安装与卸载
    Pygame之滑稽球壁碰
  • 原文地址:https://blog.csdn.net/weixin_42274953/article/details/126164385