赞
踩
记录java刷题的一个大坑,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,因为很多时候我们都要遍历数组,此时就要调用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。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。