【Java刷题】-矩阵乘法/卡牌游戏/杨辉三角

作者:学Java的冬瓜
博客主页:☀冬瓜的主页🌙
专栏:【Java刷题】

一、矩阵乘法:三层循环实现

链接:
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:
从键盘读入行数、列数和元素值,分别构建2Matrix对象,将2Matrix对象相乘,并将乘积矩阵输出到屏幕上。

输入样例:

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;
}

分析:

  1. 最外层循环j是控制ret数组的列
  2. 中间层循环i是控制ret数组的行a数组的行
  3. 最内层循环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、核心代码

用二维集合充当二维数组:

  1. 先创建一个二维集合
  2. 再创建一个一维集合并向一维集合中放入数据
  3. 把填充好数据的一维集合添加到二维集合里
	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版

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学Java的冬瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值