一、线性表(广义的数组)

在算法题中,我们一般使用到的线性表一般有两种,且它们的优缺点如下:

  • 数组

    • 优点:可以使用[]运算符进行随机读写
    • 缺点:数组大小固定,不能动态添加数据
  • List对象
    • 优点:可以动态添加数据
    • 缺点:读写数据需要使用get(int index)set(int index, Object object),和数组相比比较麻烦

1. 数组

这里数组的主要用法和c++比较类似,这里主要写一下一些特殊的操作以及Arrays工具类提供的一些方法。

一维数组的定义和初始化

① 直接指定固定大小:

int[] arr = new int[n];

则开辟的空间会填充上默认值:

  • 数值类型填充0
  • boolean类型填充false
  • 对象类型填充null

② 定义时进行初始化

int[] arr = new int[]{1, 2, 3, 4, 5};

二维数组的定义和初始化

① 和一维数组一样直接给定两个维度的大小(行数和列数):

int[][] matrix = new int[m][n];

② 和c++类似,二维数组也可以像c++中的type** matrix一样,先给第一个维度分配空间,然后再为第二个维度分配不同的空间,例如下面的代码分配下三角矩阵:

int n = 5;
int[][] matrix = new int[n][];
for (int i = 0; i < n; i++) {
matrix[i] = new int[i + 1];
}

打印展示:

Arrays工具类的一些常用方法

在Java中原生数组实际上并不是完全的面向对象的,对于List对象希望进行某项操作只需要使用.+方法即可,但数组类型本身却没有带有这些操作,因而Arrays工具类填补了这部分的空白。

Arrays.fill()

Arrays.fill有两个常见的使用:

  • Arrays.fill(int[] array, int value)
  • Arrays.fill(int[] array, int start, int end, int val)

这个函数是用于填充数组的,第一个参数是数组,第二个参数是填充的值,而第二种用法规定了填充的起止下标:[start, end)

Arrays.sort()

排序函数,一般也有两种参数填充方法:

  • Arrays.sort(int[] array)
  • Arrays.sort(Object[] array, Comparator c) tips 只有对象数组才能使用这种方式

第一种方式是按照默认的方式进行排序,数字类型按从小到大排,字符串类型按字典序排,而第二种方式中填写的第二个参数是用于改变默认的排序规则的,例如这里我希望从大到小排序():

Integer[] arr = new Integer[]{1, 2, 3, 4, 5};
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
// 或者使用下面的更加简洁的lambda表达式
Arrays.sort(arr, (num1, num2) -> num2 - num1);

由于添加Comparator对象的这种方式第一个参数只能是对象数组,因此我这里不再使用int[]而是改为了使用Integer[]

这里就会出现一个这样的需求:如果我原来的类型是int[],那么如何转换为Integer[]呢?这里我们可以使用下面的代码进行转化(其他的例如boolean到Boolean也可以按照如下方式转化):

int[] arrOrigin = new int[]{1, 2, 3, 4, 5};
Integer[] arr = (Integer[]) Arrays.stream(arrOrigin).boxed().toArray();

即将原数组转为stream对象后调用boxed方法得到Stream<Integer>,最后再调用Stream类中的toArray()成员方法即可从流重新转为数组。而Integer[]想要转为int[]则需要调用Stream类的mapToInt(Integer::intValue).toArray()

参考资料:https://codingdict.com/questions/3373

Arrays.toString(int[] array)

这个方法可以得到数组完整的内容,而如果直接使用arr.toString()只会得到对象的地址等无用信息。

Arrays.asList(int[] array)

将数组转为List对象:

Integer[] arr = new Integer[]{1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arr);

此外这个函数还可以分散填写各个List对象初始元素的值:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

⑤ 反转数组

这里可以使用工具类反转的数组也仅限是对象数组非对象数组可能只能手写反转算法了),参考代码如下:

String[] strArr = new String[]{"e", "d", "c", "b", "a"};
Collections.reverse(Arrays.asList(strArr));

输出结果:

[a, b, c, d, e]

另外还有一些例如Arrays.copyOf等方法不太常用,这里不再详细介绍。

2. List接口容器

对象的构建

实现类一般使用ArrayList(此外还有LinkedList,但不常用),构造对象方式如下:

List<Integer> list = new ArrayList<>();

读写和插入删除数据

读:E get(int index)

写:E set(int index, E element)

插入:boolean add(E e)void add(int index, E element)

删除:boolean remove(Object o)E remove(int index)

排序

使用List的接口方法sort(Comparator c)(数字从大到小排):

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.sort((num1, num2) -> num2 - num1);

输出:

[5, 4, 3, 2, 1]

或者也可以使用Collections.sort(List l, Comparator c),可以达到相同的效果。

反转数组

// Collections工具类静态方法:Collections.reverse(List list)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Collections.reverse(list);

二、字符串

以下api如果没有标注则默认为String类成员方法。

操作 api 说明
获取长度 int length()
获取下标对应字符 char charAt(int index)
转换为字符数组 char[] toCharArray()
取子串 String substring(int beginIdx, int endIdx) 其中endIdx是可选的
转为int等数字类型 静态方法 Integer.parseInt(String str) 这是int类型的,其他类型以此类推
数值类型转为字符串 静态方法 String.valueOf(T val) 这里的T可以是int、double等类型
按分隔符切分字符串 String[] split(String regex) 填入的是正则表达式
反转字符串 StringBuilder成员方法 string reverse() 需要借助StringBuilder

这些容器类基本都会包含有获取元素数量(size())和判断是否为空(empty()isEmpty())等相同的方法,因此后面的api表格只列出该类特有的操作。

三、Map和Set

1. Map

Map这里一般使用的实现为HashMap,少数需要按照键进行排序时使用到TreeMap,构造对象如下:

Map<String, String> map = new HashMap<>();

常用操作和api:

操作 api
V get(Object key)
V put(K key, V value)
是否包含key boolean containsKey(Object key)
是否包含value boolean containsValue(Object value)

遍历Map:

// 1. 使用forEach + lambda表达式(推荐)
map.forEach((key, value)-> {
...
});
// 2. 使用for结合keySet()
for (String key : map.keySet()) {
String value = map.get(key);
...
}

2. Set

和Map类似,这里Set的实现一般也选择HashSet,少数需要按照键进行排序时使用到TreeSet,构造对象如下:

Set<String> set = new HashSet<>();

常用操作和api:

操作 api
插入元素 boolean add(E e)
删除元素 boolean remove(Object o)
是否包含元素 boolean contains(Object o)

同理,set也可以使用forEach+lambda以及增强for两种写法遍历元素。

四、栈Stack和队列Queue

1. 栈Stack

构造对象:

Stack<String> stack = new Stack<>();

常用操作和api:

操作 api
压栈 E push(E item)
弹栈 E pop()
查看栈顶元素 E peek()

2. 队列Queue

Queue是一个接口,一般实现类取ArrayDeque。构造对象代码如下:

Queue<String> queue = new ArrayDeque<>();

常用操作和api:

操作 api
入队 boolean offer(E e)
出队 E poll()
查看队首 E peek()

五、优先队列

构造对象:

PriorityQueue<Integer> heap = new PriorityQueue<>();

使用无参数构造函数时得到的是小顶堆,如果我们希望得到大顶堆则需要填入一个Comparator参数,如下为构造int类型大顶堆的方式:

PriorityQueue<Integer> heap = new PriorityQueue<>((o1, o2) -> o2 - o1);

其中填入的lambda表达式为新建Comparator匿名内部类的语法糖。

常用操作和api:

操作 api
入队 boolean offer(E e)
出队 boolean poll(E e)
查看队首(堆顶) E peek()

Java刷题时常用的标准库数据结构和相应算法的更多相关文章

  1. java刷题时常用容器详解

    当初学java时,只是简单的把java基础知识过了一遍就跑去刷题了,很多知识都是在刷题的过程中慢慢加深理解的. 由于每次刷题时,刷到与容器有关的我基本上都跑去百度了,例如百度一下:java中List的 ...

  2. 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  3. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

  4. JS、JAVA刷题和C刷题的一个很重要的区别

    就是最近在做树方面的题时,发现JS和JAVA刷题和C刷题的一个很重要的区别就是传入null的区别 当遍历的时候,C传参数时可以传进去null的指针,因为递归进去,出来时,指针还是指着那个地方 但是JS ...

  5. 牛客网Java刷题知识点之为什么HashMap和HashSet区别

    不多说,直接上干货! HashMap  和  HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的 ...

  6. 牛客网Java刷题知识点之为什么HashMap不支持线程的同步,不是线程安全的?如何实现HashMap的同步?

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  7. 牛客网Java刷题知识点之ArrayList 、LinkedList 、Vector 的底层实现和区别

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  8. 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

    不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...

  9. 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

随机推荐

  1. 【记录一个问题】ndk下使用c++11的condition_variable问题较多

    1.存在通知丢失的情况:生产者线程通知196次,消费者线程收到190次,导致部分数据无法被处理. 2.cond.wait()方法后的加锁有问题,导致对空队列进行出队操作然后coredump.一直记得w ...

  2. 2022年最新黑苹果monterey安装efi分享

    最新版本monterey 12.1 安装. 配置: 名称 型号 备注 主板 Gigabyte Z490M Gaming X   内存 威刚万紫千红DDR4 2666 16G x 2 两条16G  插2 ...

  3. 动态代理jdk的Proxy与spring的CGlib

    1. 为什么要使用动态代理? 动态代理:在不改变原有代码的情况下上进行对象功能增强 使用代理对象代替原来的对象完成功能 进而达到拓展功能的目的 2.JDK Proxy 动态代理面向接口的动态代理 特点 ...

  4. linux 环境变量配置方式

    linux 环境变量可以在多个文件中配置 说明: linux bash 运行模式分为两种: login shell 和non-login shell, 两种登录模式启动是加载的配置文件不一样. 1. ...

  5. 如何在pyqt中实现平滑滚动的QScrollArea

    平滑滚动的视觉效果 Qt 自带的 QScrollArea 滚动时只能在两个像素节点之间跳变,看起来很突兀.刚开始试着用 QPropertyAnimation 来实现平滑滚动,但是效果不太理想.所以直接 ...

  6. ApacheCN Pandas 教程集

    Pandas 秘籍 零.前言 一.Pandas 基础 二.数据帧基本操作 三.开始数据分析 四.选择数据子集 五.布尔索引 六.索引对齐 七.分组以进行汇总,过滤和转换 八.将数据重组为整齐的表格 九 ...

  7. Jvm和CPU保证特定情况下不乱序

    简介 CPU为了提高指令执行效率,会在一条指令执行过程中(比去内存读数据(慢100倍)),去同时执行另一条指令,前提是,两条指令没有依赖关系. CPU保证不乱序 MESI--CPU缓存一致性协议(In ...

  8. Android编译implement、api 和compile区别【转】

    感谢大佬:https://blog.csdn.net/fengyeNom1/article/details/81903186 前言 2017 年google 后,Android studio 版本更新 ...

  9. NSMutableArray基本概念

    1.NSMutableArray介绍 什么是NSMutableArray NSMutableArray是NSArray的子类 NSArray是不可变的,一旦初始化完毕后,它里面的内容就永远是固定的, ...

  10. PHP中 die,die(),exit,exit(),return,return() 的区别

    die:是遇到错误才停止die():停止程序运行,输出内容exit:是停止程序运行,是直接停止,并且不运行后续代码,不输出内容exit():可以显示内容.exit(0):正常运行程序并退出程序:exi ...