0.小知识点
(1).length() 、length 、 size() 的区别:
length() 方法,length 属性和 size() 方法的区别:
1、length() 方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法;
2、length 属性是针对 Java 中的数组来说的,要求数组的长度可以用其 length 属性;
3、Java 中的 size() 方法是针对泛型集合说的, 如果想看这个泛型有多少个元素, 就调用此方法来查看!
(2).== 与 equal
// == 比较的是两个对象的地址值,equals() 比较的是字面值。
String a = "saff";
String b = "saff";
String c = new String("saff");
System.out.println(a.equal(b)); // true
System.out.println(a.equal(c)); // true
(3).最值
//1.整形
Integer.MAX_VALUE
Integer.MIN_VALUE
1.数组
数组常用操作
(1)数组统计:求和、均值、最大值、最小值
int[] arr1 = {1, 5, 3, 6, 7};
int sum = Arrays.stream(arr1).sum(); // 求和
OptionalDouble avg = Arrays.stream(arr1).average(); // 求平均值
double average = avg.getAsDouble();
int min = Arrays.stream(arr1).min().getAsInt(); // 最小值
int max = Arrays.stream(arr1).max().getAsInt(); // 最大值
(2)Arrays类:排序、填充、复制
//数组排序
Arrays.sort(int[] a) //将数组a从小到大排序(数组类型也可是char、float等)
int[] nums = {1,2,3,4}
Arrays.sort(nums, (a, b)->b - a); //使用lambda表达式对int数组降序排列
TreeNode head = ...;(head是链表的头指针)
Arrays.sort(head, (a, b)->b.val - a.val); //使用lambda表达式对链表根据节点的成员变量val的大小进行降序排列,
//数组填充值
void fill(int[] a, int val)//数组类型也可是char、boolean等
//复制
int[] Arrays.copyOf(int[] nums, int newLength);//复制数组nums,范围从0~newLength,并将复制后的数组return
int[] copyOfRange(int[] original, int from, int to) ;//复制数组nums,范围从from~to,并将复制后的数组return
2.字符串
基础知识:
1.使用场景
String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了。因为jdk源码中String类是用 final 修饰封装的字符数组。当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
和
小结,使用的基本原则:
如果要操作少量的数据用 String ;
单线程操作大量数据用 StringBuilder ;
多线程操作大量数据,用 StringBuffer。
2.区别
(1) StringBuilder 和 StringBuffer 之间的最大不同在于: StringBuilder 的方法不是线程安全的(不能同步访问)。 StringBuffer 是线程安全的。由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
(2) String 类不同的是, StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
(1)String
//创建
String s1 = "Runoob"; // String 直接创建
String s2 = new String("Runoob"); // String 对象创建
//数字字符串转int数组
//注意:参数字符串中只能有数字字符,否则转换失败抛出异常
String str = "123";
int a = Integer.parseInt(str); //返回int值
int b = Integer.valueOf(str); //返回Integer对象
//常用函数
char charAt(int index) //返回指定索引处的 char 值。
String concat(String str)//将指定字符串连接到此字符串的结尾。
char[] toCharArray()//将此字符串转换为一个新的字符数组。
boolean equals(Object anObject)//将此字符串与指定的对象比较。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)//将字符从此字符串复制到目标字符数组。
int length()//返回此字符串的长度。
String substring(int beginIndex, int endIndex)//返回一个新的字符串,它是此字符串的一个子字符串。
String[] split(String regex)//根据给定正则表达式的匹配拆分此字符串。
//例:
public String[] split(String regex)
String s = " the sky is blue ";
String[] strings = s.split(" ");
//strings:"","","","the","sky","is","","","","","blue","",""
比较2个字符串的大小
s1.compareTo(s2); //逐个比较对应下标的ascii码,若s1的比s2的大,返回某个正数,否则返回某个负数。详见jdk文档
System.out.println("".compareTo("a"));//return -1
System.out.println("aa".compareTo("aA"));return 32
//第一位相同,比较第二位,'a'-'A'=32
//这里并没有如十进制不同位置数字的权重,都是一样的
(2)StringBuilder
//创建
StringBuilder sb = new StringBuilder("helloigeek");
StringBuilder ss = sb.append("oo");//ss : helloigeekoo
//常用函数
StringBuilder append(Object obj) //在StringBuild末尾添加Object的String形式
setCharAt(int index, char ch)//设置指定索引位置的字符
int capacity() //返回当前StingBuilder的容量
char charAt(int index) //返回在index位置上的字符
StringBuilder delete(int start,int end) //删除从start到end位置上的子串
StringBuilder deleteCharAt(int index)//删除Index处的字符
StringBuilder insert(int offset,Object obj)//在offset处插入一个obj
String subString(int start,int end)//返回从start开始到end的子串
String toString()//转成String//类型
StringBuilder Reverse() //将所有字符顺序颠倒后返回
(3)StringBuffer
//创建
StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");//sBuffer: 菜鸟教程官网:
sBuffer.append("www");//sBuffer: 菜鸟教程官网:www
//常用函数
public StringBuffer append(String s)//将指定的字符串追加到此字符序列。
public StringBuffer reverse()// 将此字符序列用其反转形式取代。
public delete(int start, int end)//移除此序列的子字符串中的字符。
public insert(int offset, int i)//将 int 参数的字符串表示形式插入此序列中。
insert(int offset, String str)//将 str 参数的字符串插入此序列中。
replace(int start, int end, String str)//
使用给定 String 中的字符替换此序列的子字符串中的字符。
(4) 相互转化
//1.char[] 与 string
//(1) string -> char[]
String c = “Hello World.”;// 创建一个String对象
char[] cd = c.toCharArray();// 再调用String对象的toCharArray函数转换成字
//(2) char[] -> string
char[] data = {'a', 'b', 'c'};
String str = new String(data); //方法1:构造函数。
String str = String.valueOf(char[] ch); //方法2:调用String类的valueOf函数转换。
String str = String.copyValueOf(char[] ch) //方法3:
//2.String 与 StringBuilder
//(1) String -> StringBuilder
String str = "123";
StringBuilder s = new StringBuilder(str);
//(2) StringBuilder -> String
String str = s.toString();
3.Stack 栈
//创建实例
Stack<Integer> stack = new Stack<>();
//常用方法
public boolean empty() //判断是否栈空
public E peek() //获取栈顶元素,不弹出
public E pop() 弹出栈顶元素,并将其返回
public E push(E item) //元素入栈
public int search(Object o) //搜索堆栈中的元素并获取其与顶部的距离。此方法从1开始而不是从0开始计数位置。位于堆栈顶部的元素被视为在位置1。如果存在多个元素,则最接近顶部的元素的索引返回。如果成功找到该元素,则该方法返回其位置;如果缺少该元素,则返回-1。
4.Queue 队列
单向队列
//创建实例
Queue<Integer> que1 = new LinkedList<>();
//常用方法
public boolean add(E e) //将指定的元素插入到此队列中,容量不足抛出异常
public E element() //检索,但不删除,这个队列的头。
public boolean offer(E e) //如果在不违反容量限制的情况下立即执行,则将指定的元素插入到此队列中。
public E peek() //检索但不删除此队列的头,如果此队列为空,则返回 null 。
public E poll() //检索并删除此队列的头,如果此队列为空,则返回 null 。
public E remove() //检索并删除此队列的头。
public boolean isEmpty() //判空
双向队列
//创建实例
Deque<Integer> que1 = new ArrayDeque<>();
//常用方法
public void addFirst(E e) //插入此双端队列的前面,容量不足抛出异常
public void addLast(E e) //插入此双端队列的尾部,容量不足抛出异常
public boolean contains(Object o) //如果此deque包含指定的元素,则返回 true 。
public E peekFirst() //检索,但不删除,此deque的第一个元素,或返回 null如果这个deque是空的。
public E peekLast() //检索但不删除此deque的最后一个元素,如果此deque为空,则返回 null 。
public E pollFirst() //检索并删除此deque的第一个元素,如果此deque为空,则返回 null 。
public E pollLast() //检索并删除此deque的最后一个元素,如果此deque为空,则返回 null
public int size() //返回此deque中的元素数。
优先队列
//注意:不是放入优先队列里数字就是有序的,只是队头元素永远是最大值或最小值
int[] nums = new int[] { 12, 3, 8, 5, 16, 30, 9 }; //示例数组
//创建实例
//最小优先队列
Queue<Integer> queue = new PriorityQueue<>();
//最大优先队列,优先队列默认是最小优先队列,要使用最大优先队列可以重写Comparator接口
Queue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2-o1); //简写
//或:
Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//多重条件的优先队列:
Queue<QueNode> priQue = new PriorityQueue<>((a,b)->(b.heat-a.heat==0?a.words.compareTo(b.words):b.heat-a.heat));
//创建优先队列,先比较节点的heat,heat值大的优先。若有多个heat值相等的节点,则依次比较字符串ascii码的大小,ascii码小的优先。
//常用方法
public boolean add(E e);//在队尾添加元素
public E peek();//取出队头元素
public boolean remove(Object o);//删除指定元素
public boolean contains(Object o);//检查是否包含元素
public Object[] toArray();//将队列转换成数组
public int size();//返回元素个数
public void clear() ;//清空队列
public E poll(); //返回并清除队头元素
public boolean isEmpty(); //判断队列是否为空
知识点:
1.统计数组中数字出现频率,存入hashMap
2.遍历hashMap,取出键值对
3.创建大顶堆优先队列(堆排序过程和时间复杂度)
解法:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
int[] res = new int[k];
//1.统计数组中数字出现频率,存入hashMap
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
//3.创建大顶堆优先队列
PriorityQueue<Map.Entry<Integer,Integer>> que = new PriorityQueue<>((o1, o2) -> o2.getValue()-o1.getValue());
//2.遍历hashMap,取出键值对
Set<Map.Entry<Integer,Integer>> emtries = map.entrySet();
for(Map.Entry<Integer,Integer> entry : emtries){
que.add(entry);
}
for(int i=0; i<k; i++){
res[i] = que.poll().getKey();
}
return res;
}
}
2重条件的优先队列,leetcode例题:642.设计搜索自动补全系统
5.List
1.ArrayList
参考教程:菜鸟教程
//创建实例
List<Integer> list = new ArrayList<Integer>();
add(E e) //添加元素
get(int index) //根据下标获取元素
remove(int index) //根据下标移除元素
1.统计
//求和
double sum = levelList.stream().mapToDouble(Integer::intValue).sum()
//求最大值
int max = levelList.stream().mapToInt(Integer::intValue).max().getAsInt();
2.转数组
List<Integer> list = new ArrayList<Integer>();
int[] array = list.stream().mapToInt(Integer::intValue).toArray();
String[] arr = (String[])list.toArray(new String[list.size()]);
3.迭代
List<int[]> resNum = new ArrayList<>();
resNum.forEach((e) -> {
for(int i=0; i<e.length; i++){
e[i] += 1;
}
});
4.排序
// 倒序
Collections.sort(voList, (o1, o2) -> o2.getBeContactedDate().compareTo(o1.getBeContactedDate()));
// 顺序
Collections.sort(voList, (o1, o2) -> o1.getBeContactedDate().compareTo(o2.getBeContactedDate()));
5.筛选移除元素
// 现在userList中包含no为"123"的User对象
userList.removeIf(user -> "123".equals(user.getNo()));
// 现在userList中不再包含no为"123"的User对象
(2)LinkedList
参考教程:菜鸟教程
//创建实例
LinkedList<E> list = new LinkedList<E>(); // 普通创建方法
LinkedList<String> sites = new LinkedList<String>();
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
public boolean add(E e) //链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
public void add(int index, E element) //向指定位置插入元素。
6.Set
HashSet
//创建实例
Set<Integer> set = new HashSet<Integer>();
//常用函数
boolean add(E e) //添加元素,如已存在不重复添加
void clear() //清除所有元素
Returns true if this set contains the specified element.
boolean isEmpty() //判断set是否为空
boolean remove(Object o) //移除该元素
int size() //返回set元素
//遍历
for(int s:set){
S
}
7.map
hashmap
//创建实例
Map<Integer, Integer> map = new HashMap<>();
//常用函数
boolean put(K key, V value) //添加键值对
void clear() //清除所有键值对
Object get(Object key) //根据传入的键,返回对应的值,如不存在,返回null
boolean containsKey(Object key) //判断是否存在某键
boolean containsValue(Object value) //判断是否存在某值
boolean isEmpty() //判断map是否为空
Object replace(Object key, Object value) //根据键修改对应的值,并返回旧值
Object remove(Object key);
boolean remove(Object key, Object value);
int size() //返回键值对的数量
//遍历
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
//统计频数
for(int i=0; i<nums.length; i++){
map.put(nums[i], map.getOrDefault(nums[i], 0)+1);
}
8.树
1.二叉树
(1)节点的定义
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(){};
TreeNode(int val){
this.val = val;
}
TreeNdoe(int val, TreeNode left, TreeNode right){
this.val = val;
this.left = left;
this.right = right;
}
}
2.前缀树
(1)字符前缀树模板
class Trie {
Map<Character, Trie> next;
boolean isEnd;
//构造函数
public Trie() {
this.next = new HashMap<>();
this.isEnd = false;
}
//插入新字符串
public void insert(String word) {
Trie cur = this;
for(char c:word.toCharArray()){
if(cur.next.get(c) == null){ //如果当前字符不在前缀树中,则新建节点添加到树中
cur.next.put(c, new Trie());
}
cur = cur.next.get(c); //查看下一个节点
}
cur.isEnd = true; //插入字符串完成后,在最后一个字符所在节点,标记为true
}
//查找树中是否存在该字符串(单词)
public boolean search(String word) {
Trie res = searchPrefix(word);
if(res!=null && res.isEnd==true){ //如果树中存在字符串‘word’,且结尾标记为true,则返回true
return true;
}
return false;
}
//查找树中是否存在某个前缀
public boolean startsWith(String prefix) {
Trie res = searchPrefix(prefix);
if(res!=null){ //如果树中存在此前缀,则返回true
return true;
}
return false;
}
//search()和startsWith()都会需要搜索前缀,故将其封装成函数。
//注意:此处返回值是一个节点
public Trie searchPrefix(String prefix) {
Trie cur = this;
for(char c:prefix.toCharArray()){
if(cur.next.get(c)==null){ //如果当前查询节点为空,则返回空节点
return null;
}else{
cur = cur.next.get(c); //查看下一个节点
}
}
return cur;
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/