作者:学Java的冬瓜
文章目录
- 一、矩阵乘法:三层循环实现
- 1、题目
- 2、核心代码
- 3、实现代码
- 二、卡牌游戏:顺序表实现
- 1、创建牌对象
- 2、核心代码
- 3、TestPokers类的main函数
- 4、结果演示
- 三、杨辉三角:二维集合实现
- 1、直角三角形版
- 1.1、核心代码
- 1.2、测试和打印
- 1.3、结果演示
- 2、等腰三角形版
一、矩阵乘法:三层循环实现
链接:pta.实现矩阵乘法
1、题目
1、定义Matrix(矩阵)类,要求如下:
a) 静态变量:static Scanner reader=new Scanner(System.in);b) 变量:row(行数),column(列数),matrix(int型二维数组);c) 根据需求定义构造方法;d) 方法:
1) inputMatrix方法:从键盘读入行数和列数,创建矩阵的二维数组,然后从键盘读入矩阵的元素值;
2) multiply方法:两个矩阵相乘,方法将返积矩阵;
3) display方法:将矩阵输出到屏幕
2、编写Main类,测试Matrix类:
从键盘读入行数、列数和元素值,分别构建2个Matrix对象,将2个Matrix对象相乘,并将乘积矩阵输出到屏幕上。
输入样例:
2 3
1 2 3
4 5 6
3 2
7 8
9 0
1 2
输出样例:
28 14
79 44
2、核心代码
功能:实现两个矩阵相乘,并返回相乘后的矩阵。
public static int[][] multiply(int[][] a,int row1,int column1, int[][] b,int row2,int column2) {
//根据矩阵相乘的性质:行由第一个矩阵控制,列由第二个矩阵控制
//创建返回相乘结果的矩阵
int[][] ret = new int[row1][column2];
//控制ret数组的列,column2可由b[0].length代替
for (int j = 0; j < column2; j++) {
//控制ret数组的行,也是第一个数组的行。row1可由a.length代替
for (int i = 0; i < row1; i++) {
int sum = 0;
//第一个数组的列,一维数组从前往后访问,对应数据相乘,再累加,结果就是数组ret的i行j列的元素
for (int k = 0; k < column1; k++) {
sum += a[i][k] * b[k][j];
}
ret[i][j] = sum;
}
}
return ret;
}
分析:
- 最外层循环j是控制ret数组的列
- 中间层循环i是控制ret数组的行和a数组的行
- 最内层循环k是控制a数组从左到右访问,ret数组从上到下访问
所以可以分析到计算顺序是:
- 从j到i分析:先计算ret数组第一列每一行数据,再算下一列的
- 从i到k分析:a数组的第i行分别与b的第一行数据对应相乘,再相加
- k分析:控制a的一维数组的数据从左到右,b的数组的数据从上到下访问
3、实现代码
import java.util.Scanner; //导入Scanner这个类,才能创建对象进行键盘输入
//定义矩阵类
class Matrix {
int row;
int column;
int[][] matrix;
//构造方法,创建矩阵对象
public Matrix(int row, int column) {
this.row = row;
this.column = column;
this.matrix = new int[row][column];
}
//向两个对象的矩阵中输入数据
public void inputMatrix(int i, int j, int input) {
matrix[i][j] = input;
}
//矩阵相乘,返回结果矩阵
//设置为static,使用该方法直接用类名调用
public static int[][] multiply(int[][] a,int row1,int column1, int[][] b,int row2,int column2) {
int[][] ret = new int[row1][column2];
for (int j = 0; j < column2; j++) {
for (int i = 0; i < row1; i++) {
int sum = 0;
for (int k = 0; k < column1; k++) {
sum += a[i][k] * b[k][j];
}
ret[i][j] = sum;
}
}
return ret;
}
//打印
//设置为static,使用该方法直接用类名调用
public static void display(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();
}
}
}
//Main函数测试
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//创建对象
//m1
int row1 = scanner.nextInt();
int column1 = scanner.nextInt();
Matrix matrix1 = new Matrix(row1,column1);
for(int i=0; i<row1; i++) {
for(int j=0; j<column1; j++) {
int input = scanner.nextInt();
matrix1.inputMatrix(i,j,input);
}
}
//m2
int row2 = scanner.nextInt();
int column2 = scanner.nextInt();
Matrix matrix2 = new Matrix(row2,column2);
for(int i=0; i<row2; i++) {
for(int j=0; j<column2; j++) {
int input = scanner.nextInt();
matrix2.inputMatrix(i,j,input);
}
}
//乘积
int[][] ret = Matrix.multiply(matrix1.matrix,row1,column1, matrix2.matrix,row2,column2);
Matrix.display(ret);
}
}
二、卡牌游戏:顺序表实现
1、创建牌对象
public class Poker {
//1、每张牌的属性
private String suit; //代表每张牌的花色
private int rank; //代表每张牌的大小
//2、构造方法创建牌的同时初始化对象
public Poker(String suit, int rank) {
this.suit = suit;
this.rank = rank;
}
//3、重写toString方法便于打印
@Override
public String toString() {
return suit+" "+rank;
}
}
2、核心代码
功能:核心代码三个功能都可以放在Pokers类里面。
- 买一副牌
- 洗牌
- 发牌
买一副牌:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Pokers {
public static final String[] SUITS = {"♥","♦","♠","♣"};
// 一、获取一副牌
public static List<Poker> buyPokers() {
List<Poker> pokerList = new ArrayList<>();
// 1、i是SUITS的下标,从0到3表示牌的花色
for (int i = 0; i < 4; i++) {
// 2、j从1到13表示,1到13的牌
for (int j = 1; j <= 13; j++) {
String suit = SUITS[i];
// 3、得到花色和牌的大小,创建每一张牌
Poker poker = new Poker(suit,j);
// 4、把每一张牌放进这一副牌中
pokerList.add(poker);
}
}
return pokerList;
}
洗牌:
// 2、洗牌
public static void shuffle(List<Poker> pokerList) {
// 1、生成随机数
Random random = new Random();
// 2、从大到小取出牌,再和随机下标的牌交换
for (int i = pokerList.size()-1; i > 0; i--) { //要求i的范围大于0,否则i=0时,random里面i=0会出错
// 3、random里的i表示,随机数生成范围是0~i-1,不包括自己i位置,因为和自己交换没意义
int j = random.nextInt(i);
// 4、交换函数
swap(pokerList,i,j);
}
}
//交换函数,用private的目的是:达到封装的效果
private static void swap(List<Poker> pokerList, int i, int j){
Poker tmp = pokerList.get(i);
pokerList.set(i,pokerList.get(j));
pokerList.set(j,tmp);
}
发牌:
public static List<List<Poker>> givePokers(List<Poker> pokerList) {
//发牌
// 1、手中的牌定义一个二维集合
List<List<Poker>> hands = new ArrayList<>();
List<Poker> hand1 = new ArrayList<>();
List<Poker> hand2 = new ArrayList<>();
List<Poker> hand3 = new ArrayList<>();
List<Poker> hand4 = new ArrayList<>();
hands.add(hand1);
hands.add(hand2);
hands.add(hand3);
hands.add(hand4);
for (int i = 1; i <= 12; i++) { // 每个人发到十张牌
for (int j = 0; j < 4; j++) { // 有四个人
// 2、每次发牌从pokerList这副牌中取走第一张
Poker remove = pokerList.remove(0);
// 3、将取走的牌一人一张的发,然后一张一张地存入二维集合,发够10次
hands.get(j).add(remove); //每次j=0,代表发的是第一个人的牌
}
}
return hands;
}
}
3、TestPokers类的main函数
import java.util.List;
public class TestPoker {
public static void main(String[] args) {
System.out.println("买一副牌:");
List<Poker> pokerList = Pokers.buyPokers(); //如果同一个类中可以直接用static方法,不需要类名调用
System.out.println(pokerList);
System.out.println("=================================");
System.out.println("洗牌:");
Pokers.shuffle(pokerList);
System.out.println(pokerList);
System.out.println("=================================");
System.out.println("发牌:");
System.out.println("手中的牌:");
List<List<Poker>> hands = Pokers.givePokers(pokerList);
for (int i = 0; i < hands.size(); i++) {
System.out.println("第"+(i+1)+"个人的牌:"+hands.get(i));
}
System.out.println("剩下的牌:");
System.out.println(pokerList);
}
}
4、结果演示
买一副牌:
[♥ 1, ♥ 2, ♥ 3, ♥ 4, ♥ 5, ♥ 6, ♥ 7, ♥ 8, ♥ 9, ♥ 10, ♥ 11, ♥ 12, ♥ 13, ♦ 1, ♦ 2, ♦ 3, ♦ 4, ♦ 5, ♦ 6, ♦ 7, ♦ 8, ♦ 9, ♦ 10, ♦ 11, ♦ 12, ♦ 13, ♠ 1, ♠ 2, ♠ 3, ♠ 4, ♠ 5, ♠ 6, ♠ 7, ♠ 8, ♠ 9, ♠ 10, ♠ 11, ♠ 12, ♠ 13, ♣ 1, ♣ 2, ♣ 3, ♣ 4, ♣ 5, ♣ 6, ♣ 7, ♣ 8, ♣ 9, ♣ 10, ♣ 11, ♣ 12, ♣ 13]
=================================
洗牌:
[♣ 11, ♠ 7, ♥ 11, ♠ 9, ♦ 7, ♦ 1, ♣ 10, ♣ 8, ♥ 10, ♥ 8, ♠ 8, ♣ 13, ♣ 7, ♠ 13, ♣ 5, ♦ 6, ♦ 9, ♠ 11, ♣ 4, ♠ 3, ♠ 5, ♥ 1, ♦ 2, ♥ 12, ♣ 6, ♥ 13, ♥ 3, ♦ 11, ♥ 2, ♣ 1, ♣ 12, ♣ 2, ♣ 9, ♠ 10, ♥ 5, ♦ 8, ♥ 4, ♦ 3, ♦ 10, ♠ 1, ♥ 6, ♦ 4, ♠ 2, ♦ 5, ♠ 6, ♣ 3, ♠ 4, ♥ 7, ♠ 12, ♥ 9, ♦ 12, ♦ 13]
=================================
发牌:
手中的牌:
第1个人的牌:[♣ 11, ♦ 7, ♥ 10, ♣ 7, ♦ 9, ♠ 5, ♣ 6, ♥ 2, ♣ 9, ♥ 4, ♥ 6, ♠ 6]
第2个人的牌:[♠ 7, ♦ 1, ♥ 8, ♠ 13, ♠ 11, ♥ 1, ♥ 13, ♣ 1, ♠ 10, ♦ 3, ♦ 4, ♣ 3]
第3个人的牌:[♥ 11, ♣ 10, ♠ 8, ♣ 5, ♣ 4, ♦ 2, ♥ 3, ♣ 12, ♥ 5, ♦ 10, ♠ 2, ♠ 4]
第4个人的牌:[♠ 9, ♣ 8, ♣ 13, ♦ 6, ♠ 3, ♥ 12, ♦ 11, ♣ 2, ♦ 8, ♠ 1, ♦ 5, ♥ 7]
剩下的牌:
[♠ 12, ♥ 9, ♦ 12, ♦ 13]
三、杨辉三角:二维集合实现
1、直角三角形版
链接:LeetCode118.杨辉三角
1.1、核心代码
用二维集合充当二维数组:
- 先创建一个二维集合
- 再创建一个一维集合并向一维集合中放入数据
- 把填充好数据的一维集合添加到二维集合里
public static List<List<Integer>> generate(int num) {
// 1、二维集合实现二维数组,从而实现杨辉三角
List<List<Integer>> listList = new ArrayList<>();
// 2、先创建第一行对象并填充1,然后放入二维集合
List<Integer> firstRow = new ArrayList<>();
firstRow.add(1);
listList.add(firstRow);
// 3、第一行已经放入,从第二行开始放接下来的数据
for (int i = 1; i < num; i++) {
// 4、创建一维集合,最开始给1
List<Integer> curRow = new ArrayList<>();
curRow.add(1);
// 5、中间数据是上一个行j列和上一行j-1列的元素和
List<Integer> prevRow = listList.get(i-1);
//注意://设置j<i,第二行并不会进入循环,而是只添加curRow的第一个和第二个(也是最后一个)元素为1
for (int j = 1; j < i; j++) {
int value = prevRow.get(j)+prevRow.get(j-1);
curRow.add(value);
}
// 6、每行最后一个元素放入1
curRow.add(1);
// 7、把第二行开始创建的一维集合依次放入二维集合中
listList.add(curRow);
}
// 8、返回二维集合(数组的集合形式)
return listList;
}
1.2、测试和打印
public class Test {
public static void main(String[] args) {
//随便给个值例如:6
List<List<Integer>> listList = generate(6);
for (int i = 0; i < listList.size(); i++) {
List<Integer> curRow = listList.get(i);
for (int j = 0; j < curRow.size(); j++) {
System.out.print(curRow.get(j)+" ");
}
System.out.println();
}
}
}
1.3、结果演示
//num==6
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
2、等腰三角形版
说明:可以实现,但因为要控制空格,所以找下标较为麻烦,详细可以参考我以前写的博客:
链接:
博客实现杨辉三角2.0版