LeetCode进阶之路(二)java常用的数据结构
一、java常用的数据结构的特点和应用场景
1.数组
可以容纳一串数字,每个数字有单独的索引,可以方便的通过索引查找相应位置的数值是多少。
2.字符串String
一串字母,不支持用[ ]直接访问其中的字符,不能直接修改,需要用toCharArray转化成char[]才可以修改。
字符串可以直接用+拼接,但效率低,for循环中尽量用StringBuilder进行字符串的拼接。
字符串的比较用equal别用==,等号容易出现bug。
3.动态数组ArrayList
ArrayList是一个动态可修改的数组,没有固定大小限制,我们可以添加或删除元素。对数组的包装,与C++中的Vector容器功能类似。
4.双链表LinkedList
链表不会按照线性顺序存储数据,它在每一个节点里存下一个节点的地址。单链表包含两个值,当前节点的值和下一个节点的链接。
我们可以用双链表对头部和尾部的元素操作,直接操作头部的效率更高,其中contains方法的时间复杂度是O(N)因为它需要遍历整个链表。
ArrayList和LinkList都是List的子类,二者返回的结果均满足题目要求的List类型。
频繁的访问列表中某一个元素,或只需要在列表末尾添加和元素时用ArrayList。
通过循环迭代访问列表中某些元素,或频繁的在列表开头、中间、末尾等位置添加删除元素时用LinkedList。
5.哈希表HashMap
HashMap是一个散列表,存储的是键值对映射(key-value)
HashCode最多允许一条记录的键值为null,HashMap无序,不会记录插入的顺序。
6.哈希集合HashSet
不允许有重复元素的集合,允许有null值。
7.队列Queue
实现了先进先出的数据结构
8.堆栈Stack
栈(Stack)实现了一个后进先出(LIFO)的数据结构。
声明时
int对应Integer
char对应Character
二、java常用数据结构的详细使用方法。
1.数组
①初始化方法
int m=5,n=10;
//初始化一个大小为10的int数组,其中默认值初始化为0
int[] nums=new int[n];
int[] arr={1,4,3,2,2};
//为数组赋值
Arrays.fill(nums, -1);
Arrays.sort(nums); //数组排序
Collections.sort(list); //链表排序
//初始化一个m*n的二维布尔数组,其中的元素默认初始化为false
bollean[][] visited=new boolean[m][m];
②做题时如果题目以函数参数的形式传入,先做个非空检查,然后用索引下标访问其中的元素。
if(nums.length==0){
return;
}
for(int i=0;i<nums.length;i++){
//访问nums[i]
}
2.字符串String
①String 的常见特性
String s1 = "Hello world!";
//获取s1[2]中的字符
char c = s1.charAt(2);
char[] chars = s1.toCharArray();
chars[1] = 'a';
String s2 = new String(chars);
// 输出:Hello World!
System.out.println(s2);
// 一定要用equals方法判断字符串是否相同
if (s1.equals(s2)) {
System.out.println("s1-s2相同");
} else {
System.out.println("不相同");
}
// 少量的字符串拼接可以直接使用加号
String s3 = s1 + "newString";
System.out.println(s3);
// 遍历字符串中的每个字符
for(Character c:s.toCharArray()){}
②更高效的字符串拼接方式StringBuilder
StringBuilder sb = new StringBuilder();
for (char c = 'a'; c <= 'f'; c++) {
sb.append(c);
}
// append方法支持字符、字符串、数字等类型
sb.append('g').append("hij").append(123);
String res = sb.toString();
System.out.println(res);
3.动态数组ArrayList
①初始化ArrayList
// 初始化一个存储String的动态数组
ArrayList<String> Strings = new ArrayList<>();
// 初始化一个存储int的动态数组
ArrayList<Integer> nums = new ArrayList<>();
② 常用方法,用E表示元素类型
// 在数组尾部添加元素e bolean add(E e);
nums.add(68);
// 判断数组是否为空 boolean isEmpty()
System.out.println(nums.isEmpty());
// 返回数组中元素个数 int size();
System.out.println(nums.size());
// 返回索引index的元素 E get(int index);
System.out.println(nums.get(0));
//返回某个元素的index int indexOf(ArrayList list)
System.out.println(list.indexOf(34))
Arrays.sort(nums); //数组排序
Collections.sort(list); //链表排序
4.3双链表LinkedList
①初始化一个双链表
// 初始化一个存储int类型数据的双链表
LinkedList<Integer> nums = new LinkedList<>()
// 初始化一个存储String类型数据的双链表;
LinkedList<String> =new LinkedList<>();
// 链表静态赋值
Collections.addAll(nums,1,3,2);
// 数组静态赋值
int[] l=new int[]{1,2,3};
②双链表常用的方法
// 在链表尾部添加元素e void add(E e)
nums.add(18);
// 在链表头部添加元素e(相当于栈的方式 得到的List是倒序的) void addFirst(E e)
strings.addFirst("fitstChar");
// 判空 boolean isEmpty()
System.out.println(strings.isEmpty());
// 返回链表中元素个数 int size()
System.out.println(nums.size());
// 删除链表头部第一个元素 removeFirst()
strings.removeFirst();
// 删除链表尾部最后一个元素 removeLast()
nums.removeLast();
// 判断链表中是否存在元素o boolean contains(object o)
System.out.println(nums.contains(18));
System.out.println(nums.contains("fitstChar"));
5.哈希表HashMap
①HashMap的初始化方法
// 整数映射到字符串的哈希表
HashMap<Integer, String> stringMap = new HashMap<>();
// 字符串映射到数组或整数的哈希表
HashMap<String, Integer> intMap = new HashMap<>();
②常用的方法
//K表示键的类型,V代表值的类型
// 将key和value键值对存入哈希表 V put(K key,V value) 如果哈希表中有当前key,则修改相应的value
stringMap.put(28301, "star");
intMap.put("star", 28301);
// 判断哈希表中是否存在键key boolean containsKey(Object key)
System.out.println(intMap.containsKey("star"));
System.out.println(stringMap.containsKey(28301));
// 获得键key对应的值,若key不存在,返回null V get(Object key)
System.out.println(intMap.get("star"));
System.out.println(stringMap.get(28301));
// 如果key不存在,将键值对key和value存入哈希表,如果存在啥也不做 V putIfAbsent(K key,V value)
stringMap.putIfAbsent(110, "feijing");
intMap.putIfAbsent("huojing", 119);
// 获得key的值,如果key不存在,返回与Value类型相同的defaultValue V getOrDefault(Object key,V defaultValue)
System.out.println(stringMap.getOrDefault(110, "没有"));
System.out.println(intMap.getOrDefault("huoji", 1199));
//初始化map的方法
hm.put(key,hm.getOrDefault(key,0)+count);
// 获得哈希表中所有key Set<k> keySet()
System.out.println(stringMap.keySet());
System.out.println(intMap.keySet());
// 如果key存在,删除key并返回对应的值 V remove(Object key)
System.out.println(stringMap.remove(110));
System.out.println(intMap.remove("huojing"));
//遍历HashMap
Set<String> keySet = map.keySet();
for(String key:keySet){
System.out.println(key+":"+map1.get(key));
}
//K表示键的类型,V代表值的类型
// 将key和value键值对存入哈希表 V put(K key,V value) 如果哈希表中有当前key,则修改相应的value
stringMap.put(28301, "star");
intMap.put("star", 28301);
// 判断哈希表中是否存在键key boolean containsKey(Object key)
System.out.println(intMap.containsKey("star"));
System.out.println(stringMap.containsKey(28301));
// 获得键key对应的值,若key不存在,返回null V get(Object key)
System.out.println(intMap.get("star"));
System.out.println(stringMap.get(28301));
// 如果key不存在,将键值对key和value存入哈希表,如果存在啥也不做 V putIfAbsent(K key,V value)
stringMap.putIfAbsent(110, "feijing");
intMap.putIfAbsent("huojing", 119);
// 获得key的值,如果key不存在,返回与Value类型相同的defaultValue V getOrDefault(Object key,V defaultValue)
System.out.println(stringMap.getOrDefault(110, "没有"));
System.out.println(intMap.getOrDefault("huoji", 1199));
//初始化map的方法
hm.put(key,hm.getOrDefault(key,0)+count);
// 获得哈希表中所有key Set<k> keySet()
System.out.println(stringMap.keySet());
System.out.println(intMap.keySet());
// 如果key存在,删除key并返回对应的值 V remove(Object key)
System.out.println(stringMap.remove(110));
System.out.println(intMap.remove("huojing"));
//遍历HashMap
Set<String> keySet = map.keySet();
for(String key:keySet){
System.out.println(key+":"+map1.get(key));
}
6.哈希集合HashSet
①HashSet初始化方法:
//初始化一个存储int类型数据的哈希集合
Set<Integer> set = new HashSet<>();
②哈希集合常见的方法:
//如果e不存在,则将e添加到哈希表集合 boolean add(E e);
set.add(168);
////判断元素o是否存在于哈希集合中 boolean contains(Object o);
System.out.println(set.contains(168));
////如果元素o存在,则删除元素o boolean remove(Object o);
set.remove(168);
//返回集合中元素个数 set.size()
7.队列Queue
①初始化一个队列,Queue是一个接口(Interface)
//新建一个存储String的队列
Queue<String> q = new LinkedList<>();
②常用方法
//常用的一些方法,用E表示元素的类型
//判断队列是否为空 boolean isEmpty()
//返回队列中元素的个数 int size(),返回的结果不能转化为字符串,直接拼接即可
//返回队头的元素 E peek()
//删除并返回队头元素 E poll()
//将元素e插入队尾 boolean offer(E e)
q.offer("hello");
q.offer("world!");
//返回队头的元素 E peek()
//删除并返回队头元素 E poll()
//将元素e插入队尾 boolean offer(E e)
if (!q.isEmpty()) {
System.out.println(q.size());
// System.out.println( q.size().toString()); 转换类型会报错:java无法取消引用int
System.out.println("队头的元素为:" + q.peek().toString());
System.out.println("删掉队头的元素:" + q.poll().toString());
8.堆栈Stack
①初始化
//初始化一个堆栈
Stack<String> s = new Stack<>();
②常用方法
//常用的方法
//判断堆栈是否为空 boolean isEmpty()
//返回堆栈中元素的个数 int size()
//将元素压入栈顶 E push(E item)
//返回栈顶元素 E peek()
//删除并返回栈顶元素 E pop()
s.push("hello");
s.push("world");
if (!s.isEmpty()) {
System.out.println("堆栈内元素个数为:" + s.size());
System.out.println("栈顶的元素为:"s.peek().toString());
System.out.println("删除栈顶的元素为:"s.pop().toString());