前言

记录java刷题的一个大坑,ArrayList和LinkedList效率差别

题目

6235. 逐层排序二叉树所需的最少操作数目

解题思路

层次遍历,对每一层,按照排序的结果对数组进行交换,记录交换次数即可。

遇到的坑:ArrayList和LinkedList

这是第319场周赛T3,这题被卡了好久,看了题解以后发现和我的思路一样,但我的代码就是有两个测试用例超时。

经过反复提交测试,发现是初始化List时用ArrayList和LinkedList的区别。

未通过代码

class Solution {
public int minimumOperations(TreeNode root) {
//层次遍历结果
List<List<Integer>> list = levelOrder(root); int res = 0;
//加上每层按照排序结果交换的次数
for(int i = 0; i < list.size(); i++){
res += getMinswap(list.get(i));
} return res;
} List<List<Integer>> levelOrder(TreeNode root){
List<List<Integer>> list = new LinkedList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
List<Integer> tmp = new LinkedList<>();
for(int i = 0; i < size; i++){
TreeNode now = queue.poll();
tmp.add(now.val);
if(now.left != null) queue.offer(now.left);
if(now.right != null) queue.offer(now.right);
}
list.add(tmp);
}
return list;
} int getMinswap(List<Integer> nums){
if(nums.size() == 1) return 0;
int n = nums.size();
int res = 0;
List<Integer> sortedNums = new LinkedList<>(nums);
Collections.sort(sortedNums);
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < sortedNums.size(); i++){
map.put(sortedNums.get(i), i);
}
for(int i = 0; i < n; ){
if(sortedNums.get(i).equals(nums.get(i))){
i++;
continue;
}
Collections.swap(nums, i, map.get(nums.get(i)));
res++;
} return res;
} }

通过代码

class Solution {
public int minimumOperations(TreeNode root) {
//层次遍历结果
List<List<Integer>> list = levelOrder(root); int res = 0;
//加上每层按照排序结果交换的次数
for(int i = 0; i < list.size(); i++){
res += getMinswap(list.get(i));
} return res;
} List<List<Integer>> levelOrder(TreeNode root){
List<List<Integer>> list = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
List<Integer> tmp = new ArrayList<>();
for(int i = 0; i < size; i++){
TreeNode now = queue.poll();
tmp.add(now.val);
if(now.left != null) queue.offer(now.left);
if(now.right != null) queue.offer(now.right);
}
list.add(tmp);
}
return list;
} int getMinswap(List<Integer> nums){
if(nums.size() == 1) return 0;
int n = nums.size();
int res = 0;
List<Integer> sortedNums = new ArrayList<>(nums);
Collections.sort(sortedNums);
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < sortedNums.size(); i++){
map.put(sortedNums.get(i), i);
}
for(int i = 0; i < n; ){
if(sortedNums.get(i).equals(nums.get(i))){
i++;
continue;
}
Collections.swap(nums, i, map.get(nums.get(i)));
res++;
} return res;
} }

小结

把我原来的LinkedList改成ArrayList就过了。

ArrayList和LinkedList的区别

ArrayList和LinkedList有什么区别:

  1. ArrayList底层结构是顺序表(基于数组);
    LinkList是链表;
  2. ArrayList数据存放在内存空间上;
    LinkList不是存放在连续的内存空间上;
  3. ArrayList能够高效的进行“随机访问” ,时间复杂度是O(1);
  4. LinkList能够高效的进行插入删除,时间复杂度为O(1)。

在刷题的时候应该如何选择

大部分应该选择ArrayList,因为很多时候我们都要遍历数组,此时就要调用get方法访问元素,对于随机访问,ArrayList比LinkedList快。

由于LinkList能够高效的进行插入删除,在任意位置插入操作对应add(int index, E element),删除操作对应remove(int index),所以遇到这两种操作比较多的时候应该用LinkList。这种情况在我刷题的过程中遇到得比较少。

排序效率

Collections.sort()内部是归并排序,下面对ArrayList和LinkedList实现的List做一个简单的排序效率测试。

测试代码

import java.util.*;

public class Main {
public static void main(String[] args) {
int count = 10000000; List<Integer> listArray = new ArrayList<>();
List<Integer> listLinked = new LinkedList<>();
Random random = new Random();
//生成count个随机值
for (int i = 0; i < count; i++) {
int rand = random.nextInt();
listArray.add(rand);
listLinked.add(rand);
} //开始计时
long startTime1 = System.currentTimeMillis();
//对ArrayList排序
Collections.sort(listArray);
long endTime1 = System.currentTimeMillis();
long usedTime1 = (endTime1 - startTime1); //开始计时
long startTime2 = System.currentTimeMillis();
//对LinkedList排序
Collections.sort(listLinked);
long endTime2 = System.currentTimeMillis();
long usedTime2 = (endTime2 - startTime2); //打印排序时间
System.out.println("ArrayList排序用时:" + usedTime1);
System.out.println("LinkedList排序用时:" + usedTime2);
}
}

测试结果

单从排序效率来看LinkList是比ArrayList高的,然而根据我上面那道题的例子,里面也有用到排序,当我把排序的那个List改为LinkList时仍然无法通过,应该是排完序之后又对数组进行了遍历,而遍历ArrayList是快的。

遍历效率

测试代码

import java.util.*;

public class Main {
public static void main(String[] args) {
int count = 100000; List<Integer> listArray = new ArrayList<>();
List<Integer> listLinked = new LinkedList<>();
Random random = new Random();
//生成count个随机值
for (int i = 0; i < count; i++) {
int rand = random.nextInt();
listArray.add(rand);
listLinked.add(rand);
} //开始计时
long startTime1 = System.currentTimeMillis();
//对ArrayList遍历
for(int i = 0; i < listArray.size(); i++){
int a = listArray.get(i);
}
long endTime1 = System.currentTimeMillis();
long usedTime1 = (endTime1 - startTime1); //开始计时
long startTime2 = System.currentTimeMillis();
//对LinkedList遍历
for(int i = 0; i < listLinked.size(); i++){
int a = listLinked.get(i);
}
long endTime2 = System.currentTimeMillis();
long usedTime2 = (endTime2 - startTime2); //打印遍历时间
System.out.println("ArrayList遍历用时:" + usedTime1);
System.out.println("LinkedList遍历用时:" + usedTime2);
}
}

测试结果


由此可见,ArrayList的遍历效率比LinkList高,而且超出LinkList的部分大于LinkList排序超出ArrayList的部分。因此在排序和遍历操作都存在的情况,还是应该选择ArrayList。

结论

刷题的时候首选ArrayList。遇到add(int index, E element)remove(int index)操作频繁的时候,再改用LinkList。

【Java刷题】初始化List应该选择ArrayList还是LinkedList的更多相关文章

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

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

  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. 牛客网Java刷题知识点之为什么HashMap不支持线程的同步,不是线程安全的?如何实现HashMap的同步?

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

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

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

  6. 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤

    福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑         Java全栈大联盟   ...

  7. 牛客网Java刷题知识点之泛型概念的提出、什么是泛型、泛型在集合中的应用、泛型类、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 什么时候使用上限?泛型限定通配符的体现

    不多说,直接上干货! 先来看个泛型概念提出的背景的例子. GenericDemo.java package zhouls.bigdata.DataFeatureSelection; import ja ...

  8. 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数

    不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...

  9. 牛客网Java刷题知识点之构造函数与set方法、与类名同名的一般方法、构造函数中有return语句

    不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...

  10. 牛客网Java刷题知识点之关键字static、static成员变量、static成员方法、static代码块和static内部类

    不多说,直接上干货! 牛客网Java刷题知识点之关键字static static代表着什么 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中st ...

随机推荐

  1. GitLab CI/CD 自动化部署入门

    前言:因为找了B站内推,测试开发,正好知道内部使用GitLab做自动化测试,所以简单学了一下,有错误的地方请指正. 入门 初始化 cp: 无法获取'/root/node-v12.9.0-linux-x ...

  2. flutter系列之:永远不用担心组件溢出的Wrap

    目录 简介 Row和Column的困境 Wrap组件详解 总结 简介 我们在flutter中使用能够包含多个child的widget的时候,经常会遇到超出边界范围的情况,尤其是在Column和Row的 ...

  3. 3.CBV视图之csrf补充

    CBV使用csrf装饰器关闭/开启 csrf验证,直接在函数上加装饰器无效的 #方法1 from django.views import View from django.views.decorato ...

  4. RabbitMQ安装说明文档(超详细版本)

    RabbitMQ安装说明文档(超详细版本) 1. 安装依赖环境 在线安装依赖环境: yum install build-essential openssl openssl-devel unixODBC ...

  5. 项目实战:在线报价采购系统(React +SpreadJS+Echarts)

    小伙伴们对采购系统肯定不陌生,小到出差路费.部门物资采购:大到生产计划.原料成本预估都会涉及到该系统. 管理人员可以通过采购系统减少管理成本,说是管理利器毫不过分,对于采购的效率提升也有极大帮助. 但 ...

  6. [C++] - GCC和LLVM对方法 warning: non-void function does not return a value [-Wreturn-type] 的处理差异

    最近做一个C++开源项目发现一个奇怪问题,通过clang编译链接执行程序每到有一个就崩溃了,gcc下则没有此问题. 后来通过调试,发现原因是bool返回的方法是没有return语句!问题是为啥还能通过 ...

  7. Day11.2:标签的使用

    标签的使用 当我们在嵌套语句中,例如当我们在for的嵌套循环语句中,想要终止或重新开始当前循环以外的循环的时候,单独仅靠break和continue和还不够,需要在我们想要作用的循环语句处加上一个标签 ...

  8. Java:ArrayList的基本使用(学习笔记)

    ​ 集合和数组的对比(为什么要有集合) 分为俩点 1. 长度:数组的长度是固定的,集合的长度是可变的. 2. 存储类型: 数组:可以存储基本数据类型,引用数据类型. 集合:只能存储引用数据类型. 小t ...

  9. sql-lab 通关笔记

    sql-lab less1-4 加单引号报错得到报错信息 根据报错信息判断闭合条件 order by找字段数 union select找回显位置 找到回显位置正常爆数据 相同类型其他关卡 后端代码分析 ...

  10. 编码工具使用(go语言)

    1.课程介绍 Git基础课程和实操 Goland介绍以及常用快捷键使用 Go delve 调试 你想要的linux 这里都有 2.版本控制工具介绍 原始的版本控制 修改文件,保存文件副本 版本控制的起 ...