ArrayList集合的两个实例应用,有趣的洗牌算法与杨辉三角

本节课的内容,就让我们来学习一下ArrayList集合的应用,ArrayList的本质就是一个顺序表,那下面一起来学习吧
目录
一、杨辉三角
1.题目详情及链接
2.剖析题目
3.思路及代码
二、洗牌算法
1.创造牌对象
2.创造一副牌
3.洗牌操作
4.发牌操作
一、杨辉三角
这不是普通的杨辉三角,这是力扣里面的杨辉三角
1.题目详情及链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

有同学说,这里的题目也看不出跟ArrayList集合有鸡毛关系呀?我说,你别急,继续往下看

看到这里,你急了没有,题目给的类型是什么狗屎?这不就与ArrayList扯上关系了嘛,这到底是什么意思呢?接着往下看
2.剖析题目
(1)题目的要求是根据参数,生成杨辉三角的前numRows行,并返回存放杨辉三角的空间
比如:numRows=3,就生成杨辉三角的前面3行;如果你用普通的二维数组存储,那就返回该二维数组的地址。
(2)剖析返回值
我们也应该可以猜到,List<List<Integer>>也是表示二维数组的意思

此时还不算完整的二维数组,List只是一个接口,需要实例化对象

(3)我们需要将这些数字放入该二维数组中
3.思路及代码
(1)思路解析
通过面向对象的思想来完成
第一步:分析杨辉三角的规律
题目要求生成杨辉三角的前numRows行,也就是可以一行一行生成

规律是显而易见的,除了第一行,其他每行的第一个元素和最后一个元素的值都是1;从第3行开始,中间的值与前一行的值紧密相连

第二步:创建二维数组并单独完成杨辉三角的第一行
不用担心测试用例一行都没有,1<=numRows<=30
List<List<Integer>> list = new ArrayList<>();
List<Integer> first = new ArrayList<>();
//先设置第一行的元素
first.add(1);
list.add(first);
核心思想:先单独建立一个一维的顺序表,存放好一行的元素,然后再将这个一维的顺序表当成一个元素放入二维的顺序表中,后面也是一样的思想
第三步:存放第二行及后面的元素
for (int i = 1; i < numRows; i++) {//每层循环代表一行List<Integer> ret = new ArrayList<>();//定义一个一维数组
}
我们将在这个循环里面存放完成后续的行,如果只有一行,就不会进入这个循环内
第四步:分析如何将每一行存入
由前面分析知道,第二行开始,第一个和最后一个元素都是1,我们可以在前面和最后面存入1
for (int i = 1; i < numRows; i++) {//每层循环代表一行List<Integer> ret = new ArrayList<>();//定义一个一维数组//1.添加第一个元素ret.add(1);//2.设置中间元素,从第二列开始//3.添加最后元素ret.add(1);list.add(ret);//将每一行放入二维数组中}
然后中间的元素如何添加?第二行是没有中间元素的,而且中间的元素都是与前一行的元素有着紧密的关系,所以我们也需要考虑好。首先,我们需要从第二个位置开始存放;然后,第几行就说明那一行有多少个元素,就与行号绑定了关系
for (int i = 1; i < numRows; i++) {//每层循环代表一行List<Integer> ret = new ArrayList<>();//定义一个一维数组//1.添加第一个元素ret.add(1);//2.设置中间元素,从第二列开始for (int j = 1; j < i; j++) {//利用面向对象的思想,拿到元素int tmp = list.get(i-1).get(j)+list.get(i-1).get(j-1);ret.add(tmp);}//3.添加最后元素ret.add(1);list.add(ret);}
(2)完整代码
public List<List<Integer>> generate(int numRows) {List<List<Integer>> list = new ArrayList<>();List<Integer> first = new ArrayList<>();//先设置第一行的元素first.add(1);list.add(first);//从第二行开始for (int i = 1; i < numRows; i++) {//每层循环代表一行List<Integer> ret = new ArrayList<>();//定义一个一维数组//1.添加第一个元素ret.add(1);//2.设置中间元素,从第二列开始for (int j = 1; j < i; j++) {int tmp = list.get(i-1).get(j)+list.get(i-1).get(j-1);ret.add(tmp);}//3.添加最后元素ret.add(1);list.add(ret);}return list;
}
(3)总结一下思路
第一:将杨辉三角分成两个部分存储(第一行和第一行后面的)
第二:存储第一行后面的时候,又分成三部分存储(第一个元素、中间部分元素、最后一个元素)
第三:存储中间部分元素时,通过与前一行的元素的关系进行存储(利用面向对象的思想获得前一行的元素)
二、洗牌算法
其实,洗牌算法就是ArrayList的一种应用,或者运用,没有那么的高大尚,下面简单介绍洗牌算法的一些基本功能和流程
下面是程序运行起来的结果:

什么是洗牌算法?
(1)使用类和对象的知识定义一个牌对象
(2)创造出一副排序好的牌,存储在ArrayList中(有牌)
(3)然后将这些牌的顺序打乱(洗牌)
(4)将洗乱的牌随机分发给三个人(发牌)
下面开始讲解洗牌算法
1.创造牌对象
牌这个对象的属性有两个:第一是花色,第二就是号码;然后我们提供一下构造方法,在创建每一张牌的时候就赋值;最后,重写一下toString方法,用来打印牌。
public class Card {//用来定义一张牌public String suit;//牌的花色public int num;//号码public Card(String suit, int num) {this.suit = suit;this.num = num;}@Overridepublic String toString() {return suit+num;}
}
2.创造一副牌
main函数,用来实例化对象,和调用对象中的方法(创造牌的方法)
public static void main(String[] args) {PlayCard game = new PlayCard();System.out.println("设置牌:");List<Card> cards = game.setCard();System.out.println(cards);}
创建一个类,用来表示玩牌的游戏,里面存放创建牌、洗牌和发牌的操作
public class PlayCard {public static final String[] suits = {"♠","♥","♣","♦"};//定义花色的数组//1.设置牌操作public List<Card> setCard() {List<Card> cards = new ArrayList<>();//定义一个数组,用来存放所有牌for (int i = 0; i < 4; i++) {//每次循环代表一个花色for (int j = 1; j <=13 ; j++) {//13个号码String suit = suits[i];//获得一个花色Card card = new Card(suit,j);//定义一个牌对象并赋值cards.add(card);//将牌放入一个牌数组中}}return cards;//返回一副牌}
}
(1)这是一个带返回值的函数。
(2)第一层循环,代表花色;第二层循环代码号码;每循环一次:拿到一个花色和号码,然后将这两个赋值给牌对象,并将牌放入ArrayList集合中(cards)
(3)最后将这个集合返回(接收返回值就拿到了返回值)
3.洗牌操作
这里先把上一阶段创造牌的操作隐藏,独将洗牌操作
这里洗牌的思想是:(1)从后面遍历这副牌,每张牌都随机与前面某一张牌交换
(2)获得前面随机牌使用产生随机数种子
(3)交换则单独包装成一个方法
public class PlayCard {//在这里类里面操作牌:设置牌,洗牌和发牌public static final String[] suits = {"♠","♥","♣","♦"};//定义花色的数组//1.设置牌操作//这里介绍洗牌操作,所以设置牌的操作就省略了//2.洗牌操作public void shuffle(List<Card> cards) {Random random = new Random();for (int i = 51; i > 0; i--) {int index = random.nextInt(i);//随机获取一个牌下标与i下标的牌交换swap(cards,i,index);}//return cards;}private static void swap(List<Card> cards,int i,int j) {//交换两张牌Card tmp = cards.get(i);cards.set(i,cards.get(j));cards.set(j,tmp);}}
4.发牌操作
同样的,我们把前面创造牌和洗牌的操作隐藏起来,单独介绍发牌操作
我们发牌的思路是:(1)有三个人轮流接牌,每次接一张,一共接五轮(2)每个人随机接牌,每拿到一张牌,就从这副牌中删除(3)每个人拿到五张牌,每个人看作一个一维数组;要保存三个人的牌,就需要一个二维数组。
public class PlayCard {//在这里类里面操作牌:设置牌,洗牌和发牌public static final String[] suits = {"♠","♥","♣","♦"};//定义花色的数组//1.设置牌操作//2.洗牌操作//3.发牌操作public List<List<Card>> getCard(List<Card> cards) {//定义三个对象,存取牌List<Card> hand1 =new ArrayList<>();List<Card> hand2 =new ArrayList<>();List<Card> hand3 =new ArrayList<>();//定义一个二维数组,存取三个对象List<List<Card>> hand = new ArrayList<>();hand.add(hand1);hand.add(hand2);hand.add(hand3);//每个人只能拿五张牌for (int i = 0; i < 5; i++) {for (int j = 0; j < 3; j++) {Card card = cards.remove(0);//每次拿到第一张牌,并从数组中删掉//放入每个人手中hand.get(j).add(card);}}return hand;}
}
(1)用三个一维的集合代表三个一维数组 (2)再定义一个集合,存放三个一维集合 (3)第一层循环,每循环一次就是一张牌;第二层循环就是每个人轮流拿牌 (4) hand.get(j)代表第几个人,add(card)代表把这张牌给某个人
完整代码:
public static void main(String[] args) {PlayCard game = new PlayCard();System.out.println("设置牌:");List<Card> cards = game.setCard();System.out.println(cards);System.out.println("洗牌后:");game.shuffle(cards);System.out.println(cards);System.out.println("发牌:");List<List<Card>> hand = game.getCard(cards);for (int i = 0; i < 3 ; i++) {System.out.println("第"+(i+1)+"个人的牌为:"+hand.get(i));}System.out.println("剩余的牌为:");System.out.println(cards);}
public class Card {//用来定义一张牌public String suit;//牌的花色public int num;//号码public Card(String suit, int num) {this.suit = suit;this.num = num;}@Overridepublic String toString() {return suit+num;}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;public class PlayCard {//在这里类里面操作牌:设置牌,洗牌和发牌public static final String[] suits = {"♠","♥","♣","♦"};//定义花色的数组//1.设置牌操作public List<Card> setCard() {List<Card> cards = new ArrayList<>();//定义一个数组,用来存放所有牌for (int i = 0; i < 4; i++) {//四种花色for (int j = 1; j <=13 ; j++) {//13个号码String suit = suits[i];//获得一个花色Card card = new Card(suit,j);//定义一个牌对象并赋值cards.add(card);//将牌放入一个牌数组中}}return cards;//返回一副牌}//2.洗牌操作public void shuffle(List<Card> cards) {Random random = new Random();for (int i = 51; i > 0; i--) {int index = random.nextInt(i);//随机获取一个牌下标与i下标的牌交换swap(cards,i,index);}//return cards;}private static void swap(List<Card> cards,int i,int j) {//交换两张牌Card tmp = cards.get(i);cards.set(i,cards.get(j));cards.set(j,tmp);}//3.发牌操作public List<List<Card>> getCard(List<Card> cards) {//定义三个对象,存取牌List<Card> hand1 =new ArrayList<>();List<Card> hand2 =new ArrayList<>();List<Card> hand3 =new ArrayList<>();//定义一个二维数组,存取三个对象List<List<Card>> hand = new ArrayList<>();hand.add(hand1);hand.add(hand2);hand.add(hand3);//每个人只能拿五张牌for (int i = 0; i < 5; i++) {for (int j = 0; j < 3; j++) {Card card = cards.remove(0);//每次拿到第一张牌,并从数组中删掉//放入每个人手中hand.get(j).add(card);}}return hand;}
}
本节的内容就是介绍ArrayList集合的用法,可以当成一维数组,也可以当成二维数组。看到这里本机就结束了,快趁着这个感觉去刷题吧!
相关文章:
ArrayList集合的两个实例应用,有趣的洗牌算法与杨辉三角
本节课的内容,就让我们来学习一下ArrayList集合的应用,ArrayList的本质就是一个顺序表,那下面一起来学习吧 目录 一、杨辉三角 1.题目详情及链接 2.剖析题目 3.思路及代码 二、洗牌算法 1.创造牌对象 2.创造一副牌 3.洗牌操作 4.发…...
Qt 剪贴板操作
Qt剪贴板操作 剪贴板的操作经常和前面所说的拖放技术在一起使用,因此我们现在先来说说剪贴板的相关操作。大家对剪贴板都很熟悉。我们可以简单的把它理解成一个数据的存储池,可以把外面的数据放置进去,也可以把里面的数据取出来。剪贴板是由操作系统维护的,所以这提供了跨…...
python 学习笔记20 批量修改页眉页脚
需求:修改指定目录下所有文件的页眉页脚,或者往里面添加内容。 1. 这里做了word的实现和excel的实现,如下: 需要先安装 pip3 install pywin32,另外页眉页脚格式设置可以参考: word: 浅谈Wor…...
IIS + Axios 跨域设置
1、服务器端设置IIS (web.config) 即可,不需要对django settings.py做配置(python manage.py runserver 才需要settings.py配置跨域,IIS在iis上配) 网站根目录的web.config中加上这段: <httpProtocol&…...
详细说说vuex
Vuex 是什么 Vuex有几个属性及作用注意事项vuex 使用举例Vuex3和Vuex4有哪些区别 创建 Store 的方式在组件中使用 Store辅助函数的用法响应式的改进Vuex4 支持多例模式 Vuex 是什么 Vuex是一个专门为Vue.js应用设计的状态管理构架,它统一管理和维护各个Vue组件的可…...
Qt之Ui样式表不影响子类的配置
Qt之Ui样式表不影响子类的配置 问题 在ui界面上布局时,当对容器进行样试设计时,会对容器内其它成员对象也进行了修改 分析 对应*.ui文件内容 从这个写法来看,它的样式属性会影响其成员对象样式属性。 解决方法 在容器的样式表中写时适…...
Java集合--Map
1、Map集合概述 在Java的集合框架中,Map为双列集合,在Map中的元素是成对以<K,V>键值对的形式存在的,通过键可以找对所对应的值。Map接口有许多的实现类,各自都具有不同的性能和用途。常用的Map接口实现类有HashMap、Hashtab…...
C语言—每日选择题—Day48
第一题 1. 已知宏定义: #define M y*y3*y , 则表达式 s3*M4*My*M 预处理阶段后的结果是 A:s3*(y*y3*y)4*(y*y3*y)y*(y*y3*y) B:s3*(y*y)3*y4*(y*y)3*yy*(y*y)3*y C:s3*y*y3*y4*y*y3*yy*y*y3*y D:s3*(y*y)(3…...
华为OD试题七(IPv4地址转换成整数、比赛的冠亚季军)
1. IPv4地址转换成整数 示例代码: #测试数据 s1 "100#101#1#5"def fun(s):s_list s.split("#")# 转化成十六进制数 左边补零s_16_list [hex(int(_))[2:].zfill(2) for _ in s_list]s_16_str .join(s_16_list)return int(s_16_str,16) r f…...
SVN优缺点详解及版本控制系统选型建议
Subversion (SVN)是目前可用的众多版本控制选项之一。本篇文章将全面概述什么是 SVN、SVN的历史、SVN存储库是什么,以及在切换到SVN之前您应该谨慎考虑的潜在问题。 什么是Subversion(SVN)? Subversion软件,也称为SV…...
自己动手写数据库: select 查询语句对应查询树的构造和执行
首先我们需要给原来代码打个补丁,在SelectScan 结构体初始化时需要传入 UpdateScan 接口对象,但很多时候我们需要传入的是 Scan 对象,因此我们需要做一个转换,也就是当初始化 SelectScan 时,如果传入的是 Scan 对象&am…...
扬声器(喇叭)
扬声器(喇叭) 电子元器件百科 文章目录 扬声器(喇叭)前言一、扬声器(喇叭)是什么二、扬声器(喇叭)的类别三、扬声器(喇叭)的应用场景四、扬声器(喇叭)的作用原理总结前言 扬声器广泛应用于音响系统、公共广播系统、汽车音响、电视、电脑和移动设备等各种电子设备…...
汇总大厂-校招/社招 Java面试题--持续补充更新中-大家别光收藏,要看起来,巩固基础,就是干呀!
** 接上篇-汇总大厂-校招/社招 Java面试题(补充) ** markdown文件。持续更新中(阿里、腾讯、网易、美团、京东、华为、快手、字节…) 上面这篇也结合着看啊,通宵给整理出来的。 如需下载整套资料。关注公众号后台。…...
六. 函数
基本使用 ts与js一样拥有具名函数和匿名函数两种函数类型。但是ts的函数需要提前定义好参数类型以及函数的返回值类型。 具名函数 function add(num1: number, num2: number):number {return num1 num2 }匿名函数 匿名函数的定义相对麻烦,我们需要提前定义函数的…...
SpringBoot的Starter自动化配置,自己编写配置maven依赖且使用及短信发送案例
目录 一、Starter机制 1. 是什么 2. 有什么用 3. 应用场景 二、短信发送案例 1. 创建 2. 配置 3. 编写 4. 形成依赖 6. 其他项目的使用 每篇一获 一、Starter机制 1. 是什么 SpringBoot中的starter是一种非常重要的机制(自动化配置),能够抛弃以前繁杂…...
<蓝桥杯软件赛>零基础备赛20周--第9周--前缀和与差分
报名明年4月蓝桥杯软件赛的同学们,如果你是大一零基础,目前懵懂中,不知该怎么办,可以看看本博客系列:备赛20周合集 20周的完整安排请点击:20周计划 每周发1个博客,共20周(读者可以按…...
LeetCode-2487. 从链表中移除节点【栈 递归 链表 单调栈】
LeetCode-2487. 从链表中移除节点【栈 递归 链表 单调栈】 题目描述:解题思路一:可以将链表转为数组,然后从后往前遍历,遇到大于等于当前元素的就入栈,最终栈里面的元素即是最终的答案。解题思路二:递归&am…...
Redisson分布式锁原理分析
1.Redisson实现分布式锁 在分布式系统中,涉及到多个实例对同一资源加锁的情况,传统的synchronized、ReentrantLock等单进程加锁的API就不再适用,此时就需要使用分布式锁来保证多服务之间加锁的安全性。 常见的分布式锁的实现方式有ÿ…...
【Linux】:线程(二)互斥
互斥与同步 一.线程的局部存储二.线程的分离三.互斥1.一些概念2.上锁3.锁的原理4.死锁 一.线程的局部存储 例子 可以看到全局变量是所有线程共享的,如果我们想要每个线程都单独访问g_val怎么办呢?其实我们可以在它前面加上__thread修饰。 这就相当于把g…...
vscode报错Pylance client: couldn‘t create connection to server.
问题描述: 一打开vscode,右下角就弹报错,Pylance client: couldn’t create connection to server.,让我打开output,打开后似乎是在说连不上server 因为连不上server,所以我的python代码没法解析࿰…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
