数据结构之ArrayList与顺序表(下)

news2024/11/27 22:40:33

找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏:数据结构(Java版)

目录

ArrayList的具体使用 

118. 杨辉三角

扑克洗牌算法 


接上篇:数据结构之ArrayList与顺序表(上)-CSDN博客

ArrayList的具体使用 

118. 杨辉三角

给定一个非负整数 numRows生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例 2:

输入: numRows = 1
输出: [[1]]
  • 1 <= numRows <= 30

分析:首先是一个杨辉三角的问题,杨辉三角其实就是一个只有一半的二维数组。 

public class Test {
    public static void main(String[] args) {
        // 打印杨辉三角
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int count = 0;
        // 创建一个n行n列的二维数组
        int[][] array = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j) {
                    array[i][j] = 1;
                }else if (j == 0) {
                    array[i][j] = 1;
                }else {
                    // 只有从第二行开始才会有下面的规律
                    if (i >= 2) {
                        array[i][j] = array[i-1][j] + array[i-1][j-1];
                    }
                }
            }
        }
        for (int[] x:array) {
            for (int y:x) {
                if (y != 0) {
                    System.out.print(y+" ");
                }
            }
            System.out.println();
        }
    }
}

打印结果:

注意:杨辉三角还有一个规律就是第 i-1 行有 i 个元素。 

这里主要的难点是:List<List<Integer>>   这个代码的意思是什么?分开看,List<Integer> 这个代码的意思是有一个线性表,这个线性表中存放的是 Integer 类型。List<List<Integer>> 难道这个代码的意思是有一个线性表,这个线性表里面存放的是一个线性表?没错!不过这个不叫线性表了。如果我们把这个List看成一个数组,那就是一个数组里面存放的是一个一个的数组元素,然后这些数组元素里面的元素是一个一个的整形包装类。这就是二维数组嘛!二维数组里面是一个一个的一维数组,而一维数组里面是一个一个的整型元素。

例如:

public class Test {
    public static void main(String[] args) {
        // 二维数组
        // 根据顺序表的特点这个二维数组为0行0列
        List<List<Integer>> list = new ArrayList<>(); 
        //二维数组的初始化
        list.add(new ArrayList<>()); // 二维数组的元素是一维数组
        list.add(new ArrayList<>()); // 二维数组的元素是一维数组
        list.add(new ArrayList<>()); // 二维数组的元素是一维数组
        // 一维数组的初始化
        list.get(0).add(10); // list.get(0)得到的是下标为0的一维数组,接着尾插10
        list.get(1).add(20); // list.get(1)得到的是下标为1的一维数组,接着尾插20
        list.get(2).add(30); // list.get(2)得到的是下标为2的一维数组,接着尾插30
    }
}

画图理解:

 上面搞懂了,就可以开始做题了。这个题目的意思就是让我们把存放杨辉三角二维数组改成一个ArrayList。

根据我们用二维数组做题时的代码改编一下就可以了。

下面是改编的代码:

方法一:

public class Test {
    public static List<List<Integer>> generate(int numRows) {
        // 创建一个二维数组
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        for (int i = 0; i < numRows; i++) {
            // 不用下标直接尾插也是可以的
            list.add(i, new ArrayList<>());
        }
        // 开始为二维数组存放元素
        for (int i = 0; i < numRows; i++) {
            List<Integer> list1 = list.get(i);
            //        注意这里j的条件
            for (int j = 0; j <= i; j++) {
                if (i == j) {
                    list1.add(1);
                }else if (j == 0) {
                    list1.add(1);
                }else if (i >= 2) {
                    // 实现这个代码:a[i][j] = a[i-1][j]+a[i-1][j-1];
                    // 得到i-1下标数组的j位置的值  得到i-1下标数组的j-1位置的值

                    // 这个写法有问题。就像:3 = 5
                    // list.get(i).get(j) = list.get(i-1).get(j)  + list.get(i-1).get(j-1);
                    // 这个就是对上面的代码进行翻译一下
                    int t  = list.get(i - 1).get(j) + list.get(i - 1).get(j - 1);
                    list1.add(j , t);
                }
            }
        }
        return list;
    }
    public static void main(String[] args) {
        List<List<Integer>> listList = generate(5);
        for (List<Integer> list : listList) {
            for (Integer x : list) {
                System.out.print(x+" ");
            }
            System.out.println();
        }
    }
}

方法二: 

public class TestDrive {
    public static List<List<Integer>> generate(int numRows) {
        // 创建一个二维数组
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        for (int i = 0; i < numRows; i++) {
            // 不用下标直接尾插也是可以的
            list.add(i, new ArrayList<>());
            // 为二维数组的每一位元素的初始化为0
            for (int j = 0; j < numRows; j++) {
                list.get(i).add(j,0);
            }
        }
        // 开始为二维数组存放元素
        for (int i = 0; i < numRows; i++) {
            List<Integer> list1 = list.get(i);
            //      注意这里的j和方法进行区别
            for (int j = 0; j < numRows; j++) {
                if (i == j) {
                    // 因为所有元素都有初始值了,所以这里就都是set而不是add
                    list1.set(j,1);
                }else if (j == 0) {
                    list1.set(j,1);
                }else if (i >= 2) {
                    int t  = list.get(i - 1).get(j) + list.get(i - 1).get(j - 1);
                    list1.set(j , t);
                }
            }
        }
        return list;
    }
    public static void main(String[] args) {
        List<List<Integer>> listList = generate(5);
        for (List<Integer> list : listList) {
            for (Integer x : list) {
                if (x != 0) {
                    System.out.print(x+" ");
                }
            }
            System.out.println();
        }
    }
}

方法一与方法二的区别:

方法二就是完全对前面代码的改编。因为前面我们在创建一个二维数组的同时是进行了初始化的,所以这里的所有元素都是有初始值的。但我们用顺序表来创建二维数组的时候,如果没有初始化,那么其值就是null,这个是不能参与运算的。因此,我们要手动的置为0,这样就可以参与运算了,否则就会发生异常。

方法一就是改进了方法二的不足之处。既然你不初始化,在运算时,会发生异常,那么我就把你的范围卡在只参与运算的部分。也就是 j <= i 。我们仔细观察会发现杨辉三角是一个等腰直角三角形。如下图:

杨辉三角练习完了,接下来,就要进入重磅戏了:扑克洗牌算法。 

扑克洗牌算法 

要求:

1. 生成一副扑克牌。

2. 并且把这副扑克牌打乱。

3. 发给3个人,每人每轮发一张,总共发5轮。 

一张一张的牌,一张牌包括牌面值和花色 

// 一张牌
public class Card {
    public int rank; // 牌面值
    public String suit; // 对应的花色

    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }

    @Override
    public String toString() {
        return ""+suit+rank+" ";
    }
}

有了一张一张的牌,就可以生成一副牌和存放牌的容器,也就是顺序表

public class Cards {
    // 生成牌的四色
    public static final String suit[] = {"♠","♣","♥","♦"};
    public List<Card> cardList;

    // 在new一个对象的时候,就会生成存储一副牌的数组
    public Cards() {
        this.cardList = new ArrayList<>();
    }

    // 生成一副牌
    // 为了方便,这里的牌面值都用数字表示
    public List<Card> generateCards() {
        for (int i = 1; i <= 14; i++) {
            int count = 0;
            for (int j = 0; j < suit.length; j++) {
                // 生成一张牌
                Card card = new Card(i, suit[j]);
                // 把牌存放到数组中
                cardList.add(card);
                if (i > 13 && count < 2) {
                    count++;
                }
                if (count == 2) {
                    break;
                }
            }
        }
        return cardList;
    }
}

接下来就是要开始洗牌了。

    // 洗牌
    public void shuffle() {
        // 通过随机下标进行交换
        Random random = new Random();
        // i=0就是自己和自己交换了
        for (int i = cardList.size()-1; i > 0; i--) {
            // 生成[0,i)之间的值,也就是[0,i-1]
            int index = random.nextInt(i);
            swap(cardList, index, i);
        }
    }

    private void swap(List<Card> cardList, int index, int i) {
        // 交换index和i下标对应的数组元素
        // int tmp = a; a = b; b = tmp;
        Card tmp = cardList.get(i);
        // 把i下标的值,改为index下标对应的值
        cardList.set(i, cardList.get(index));
        cardList.set(index, tmp);
    }

 发牌

    // 发牌
    // 给3人发5轮牌,每人每轮发一张
    public List<List<Card>> dealCards() {
        // 创建一个二维数组
        List<List<Card>> listList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            listList.add(new ArrayList<>());
        }
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 3; j++) {
                // 第j个人拿到第0下标的牌
                listList.get(j).add(cardList.get(0)); // 假设从最上面开始拿
                // 每拿一张就少一张
                cardList.remove(0);
            }
        }
        return listList;
    }

测试:

public class Test {
    public static void main(String[] args) {
        // 生成一副牌
        Cards cards = new Cards();
        List<Card> cardList = cards.generateCards();
        System.out.println(cardList);

        // 开始洗牌——将牌的顺序打乱
        cards.shuffle();
        System.out.println(cardList);

        // 开始发牌
        List<List<Card>> listList = cards.dealCards();


        // 查看结果
        int i = 1;
        for (List<Card> list: listList) {
            System.out.print("第"+i+"个人拿到的牌:");
            for (Card x : list) {
                System.out.print(x+" ");
            }
            i++;
            System.out.println();
        }
    }
}

 好啦!本期 数据结构之ArrayList与顺序表(下)的学习就到此结束啦!我们下一期再一起学习吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1802794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三端植物大战僵尸杂交版来了

Hi&#xff0c;好久不见&#xff0c;最近植物大战僵尸杂交版蛮火的 那今天苏音整理给大家三端的植物大战僵尸杂交版包括【苹果端、电脑端、安卓端】 想要下载的直接划到最下方即可下载。 植物大战僵尸&#xff0c;作为一款古老的单机游戏&#xff0c;近期随着B站一位UP主潜艇…

英伟达黄仁勋最新主题演讲:“机器人时代“已经到来

6月2日&#xff0c;英伟达联合创始人兼首席执行官黄仁勋在Computex 2024&#xff08;2024台北国际电脑展&#xff09;上发表主题演讲&#xff0c;分享了人工智能时代如何助推全球新产业革命。 黄仁勋表示&#xff0c;机器人时代已经到来&#xff0c;将来所有移动的物体都将实现…

开源与新质生产力

在这个信息技术迅猛发展的时代&#xff0c;全球范围内的产业都在经历着深刻的变革。在这样的背景下&#xff0c;“新质生产力”的概念引起了广泛的讨论。无论是已经成为或正努力转型成为新质生产力的企业&#xff0c;都在寻求新的增长动力和竞争优势。作为一名长期从事开源领域…

什么是2+1退休模式?什么是链动2+1模式?

21退休模式又称链动21模式&#xff0c;主要是建立团队模式&#xff0c;同时快速提升销量。是目前成熟模式中裂变速度最快的模式。21退休模式合理合规&#xff0c;同时激励用户公司的利润分享机制&#xff0c;让您在享受购物折扣的同时&#xff0c;也能促进并获得客观收益。 模…

kettle从入门到精通 第六十六课 ETL之kettle kettle阻塞教程,轻松获取最后一行数据,so easy

场景:ETL沟通交流群内有小伙伴反馈,如何在同步一批数据完成之后记录下同步结果呢?或者是调用后续步骤、存储过程、三方接口等。 解决:使用步骤Blocking step进行阻塞处理即可。 1、下面的demo演示从表t1同步数据至表t2(t1表中有三条数据,t2为空表,两个表表结构相同),…

Plotly : 超好用的Python可视化工具

文章目录 安装&#xff1a;开始你的 Plotly 之旅基本折线图&#xff1a;简单却强大的起点带颜色的散点图&#xff1a;数据的多彩世界三维曲面图&#xff1a;探索数据的深度气泡图&#xff1a;让世界看到你的数据小提琴图&#xff1a;数据分布的优雅展现旭日图&#xff1a;分层数…

Vue学习day05笔记

day05 一、学习目标 1.自定义指令 基本语法&#xff08;全局、局部注册&#xff09;指令的值v-loading的指令封装 2.插槽 默认插槽具名插槽作用域插槽 3.综合案例&#xff1a;商品列表 MyTag组件封装MyTable组件封装 4.路由入门 单页应用程序路由VueRouter的基本使用 …

认识Java中的String类

前言 大家好呀&#xff0c;本期将要带大家认识一下Java中的String类&#xff0c;本期注意带大家认识一些String类常用方法&#xff0c;和区分StringBuffer和StringBuilder感谢大家收看 一&#xff0c;String对象构造方法与原理 String类为我们提供了非常多的重载的构造方法让…

kubesz(一键安装k8s)

引言 Kubernetes&#xff08;K8s&#xff09;是一个开源的容器编排系统&#xff0c;用于自动化部署、扩展和管理容器化应用程序。kubeasz 是一个用于快速搭建 Kubernetes 高可用集群的项目&#xff0c;它基于 Ansible&#xff0c;通过提供一套简单、易用的配置&#xff0c;使得…

java异常处理知识点总结

一.前提知识 首先当运行出错的时候&#xff0c;有两种情况&#xff0c;一种叫做“错误”&#xff0c;另一种叫做“异常”。错误指的是运行过程中遇到了硬件或操作系统出错&#xff0c;这种情况程序员是没办法处理的&#xff0c;因为这是硬件和系统的问题&#xff0c;不能靠代码…

Linux: ubi rootfs 故障案例 (1)

文章目录 1. 前言2. ubi rootfs 故障现场3. 故障分析与解决4. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. ubi rootfs 故障现场 问题故障内核日志如下&#xff1a; Starting ker…

【数据结构与算法 | 二叉树篇】力扣101, 104, 111,LCR144

1. 力扣101 : 对称二叉树 (1). 题 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false…

Go语言 几种常见的IO模型用法 和 netpoll与原生GoNet对比

【go基础】16.I/O模型与网络轮询器netpoller_go中的多路io复用模型-CSDN博客 字节开源的netPoll多路复用器源码解析-CSDN博客 一、几种常见的IO模型 1. 阻塞I/O (1) 解释&#xff1a; 用户调用如accept、read等系统调用&#xff0c;向内核发起I/O请求后&#xff0c;应用程序…

多样本上下文学习:开拓大模型的新领域

大模型&#xff08;LLMs&#xff09;在少量样本上下文学习&#xff08;ICL&#xff09;中展现出了卓越的能力&#xff0c;即通过在推理过程中提供少量输入输出示例来学习&#xff0c;而无需更新权重。随着上下文窗口的扩展&#xff0c;我们现在可以探索包含数百甚至数千个示例的…

基于JSP技术的文物管理系统

你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 管理员界面 用户前台…

步态控制之ZMP

零力矩点&#xff08;Zero Moment Point&#xff0c;ZMP&#xff09;概述 ZMP步态控制是人形机器人步态控制中的一个关键概念&#xff0c;旨在确保机器人在行走或站立过程中保持平衡。ZMP是指机器人接触面上力矩为零的点&#xff0c;确保在该点上机器人不会倾倒。这个示例展示…

Python的登录注册界面跳转汽车主页面

1.登录注册界面的代码&#xff1a; import tkinter as tk from tkinter import messagebox,ttk from tkinter import simpledialog from ui.car_ui import start_car_ui# 设置主题风格 style ttk.Style() style.theme_use("default") # 可以根据需要选择不同的主题…

竞拍商城系统源码后端PHP+前端UNIAPP

下载地址&#xff1a;竞拍商城系统源码后端PHP前端UNIAPP

Live800:深度解析,客户服务如何塑造品牌形象

在当今竞争激烈的市场环境中&#xff0c;品牌形象对于企业的成功至关重要。而客户服务作为品牌与消费者之间最直接的互动方式&#xff0c;不仅影响着消费者的购买决策&#xff0c;更在塑造品牌形象方面发挥着不可替代的作用。本文将深度解析客户服务如何塑造品牌形象&#xff0…

1074 宇宙无敌加法器(测试点5)

solution 每位权值不同的高精度加法测试点5&#xff1a;结果为0的情况 #include<iostream> #include<string> using namespace std; int main(){string rule, a, b, ans "";int carry 0, temp, cnt, power;cin >> rule >> a >> b;…