打表技巧和矩阵处理技巧

本文通过三个案例展示了如何利用打表技巧解决实际问题,涉及苹果装袋优化、青草分配竞赛和连续整数和的分解。同时,介绍了矩阵处理的三种场景,包括锯齿形打印、螺旋顺序打印和原地旋转。这些实例体现了在算法设计中运用暴力求解、矩阵操作和逻辑推理的方法。
摘要由CSDN通过智能技术生成

打表找规律应用场景

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

1.打表技巧实际案例

案例一:

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

public class 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));
		}

	}

}

案例二:

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

public class EatGrass {

	// 如果n份草,最终先手赢,返回"先手"
	// 如果n份草,最终后手赢,返回"后手"
	public static String winner1(int n) {
		//0  1  2  3  4
		//后 先 后 先 先
		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));
		}
	}

}

案例三:

        对于一个正整数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个数的和,所以前一种是有效解。

public class 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) {

        //判断num是不是2的某次方 	==0是2的某次方           !=0不是2的某次方   
		//十进制8的二进制表示为  
         //   00001000 减去1后二进制形式为00000111 与原来二进制数字与操作后结果为0
        //再例如十进制10二进制表示为    00001010  减去1后二进制表示为00001001
        //00001010 & 00001001 = 00001000 不为0
        if (num < 3) {
			return false;
		}
		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");

	}
}

2.矩阵处理实际案例

案例一:zigzag打印矩阵。

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

public class ZigZagPrintMatrix {

	public static void printMatrixZigZag(int[][] matrix) {
		int Ar = 0;
		int Ac = 0;
		int Br = 0;
		int Bc = 0;
		int Endr = matrix.length - 1;
		int Endc = matrix[0].length - 1;
		boolean fromUp = false;//是不是从右上向左下打印
		while (Ar != Endr + 1) {
			printLevel(matrix, Ar, Ac, Br, Bc, fromUp);
			Ar = Ac == Endc ? Ar + 1 : Ar;
			Ac = Ac == Endc ? Ac : Ac + 1;
			
			Bc = Br == Endr ? Bc + 1 : Bc;
			Br = Br == Endr ? Br : Br + 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);

	}

}

案例二:转圈打印矩阵

        给定一个整型矩阵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]

public class 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 a, int b, int c, int d) {
		if (a == c) {
			for (int i = b; i <= d; i++) {
				System.out.print(m[a][i] + " ");
			}
		} else if (b == d) {
			for (int i = a; i <= c; i++) {
				System.out.print(m[i][b] + " ");
			}
		} else {
			int curC = b;
			int curR = a;
			while (curC != d) {
				System.out.print(m[a][curC] + " ");
				curC++;
			}
			while (curR != c) {
				System.out.print(m[curR][d] + " ");
				curR++;
			}
			while (curC != b) {
				System.out.print(m[c][curC] + " ");
				curC--;
			}
			while (curR != a) {
				System.out.print(m[curR][b] + " ");
				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);

	}

}

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

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

public class 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);

	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值