java刷算法题常用方法整理
数据类型、接口和类
接口:抽象方法的集合,但没有特定方法的实现
类:通过继承接口从而继承接口的抽象方法并针对不同的方法有自己的实现
接口 | 特点 | 常用类 |
---|---|---|
List | 元素不唯一 | LinkedList、ArrayList |
Set | 元素唯一 | HashSet、TreeSet |
Map | 键值映射 | HashMap、TreeMap |
常用类列表
该部分仅列出了在算法题中经常用到的类型与数据结构。
类 | 适用情况 |
---|---|
数组 Array | 既定长度,可模拟pair、tuple等immutable容器 |
动态数组 ArrayList | 长度动态可改的灵活数组 |
栈 Stack | LIFO后进先出 |
队列 Queue | FIFO先进先出 |
集合 HashSet | 当需要存储非重复元素或去重时,优先考虑该类型,但其不保证有序 |
哈希表 HashMap | 实现O(1)的读取与写入键值对,但其不保证有序 |
优先队列 PriorityQueue | 利用Heap进行排序性存值 |
数字 & 数学 - Number & Math
用途 | 语法 | 备注 |
---|---|---|
最大整数 | Integer.MAX_VALUE |
|
最小整数 |
Integer.MIN_VALUE |
Collection接口
Collection的定义如下:
public interface Collection<E> extends Iterable<E> {}
基础API接口:
abstract boolean add(E object)
abstract boolean addAll(Collection<? extends E> collection)
abstract void clear()
abstract boolean contains(Object object)
abstract boolean isEmpty()
abstract boolean remove(Object object)
abstract boolean removeAll(Collection<?> collection)
abstract int size()
abstract <T> T[] toArray(T[] array)
abstract Object[] toArray()
静态数组 array
属性 length
.length
记得是属性而不是方法 arr.length
没有()
工具类Arrays
返回由指定数组支持的固定大小的列表返回由指定数组支持的固定大小的列表
sort(T[] a)
将指定的数组按升序排序
String toString(T[] a)
返回指定数组内容的字符串表示形式
动态数组 List & ArrayList
初始化
常规 - ArrayList更常用
List<Integer> array = new ArrayList<>(); // 数组
List<Integer> list = new LinkedList<>(); // 链表
ArrayList 构造器
ArrayList()
ArrayList(int initialCapacity)
ArrayList(Collection<? extends E> c)
oid |
add(int index, E element) |
将指定的元素插入此列表中的指定位置。 |
---|---|---|
boolean |
add(E e) |
将指定的元素追加到此列表的末尾。 |
boolean |
contains(Object o) |
返回 |
---|
E |
get(int index) |
返回此列表中指定位置的元素 |
---|
boolean |
isEmpty() |
Returns |
---|
E |
remove(int index) |
删除此列表中指定位置的元素。 |
---|---|---|
boolean |
remove(Object o) |
如果存在指定元素,则从该列表中删除该元素的第一次出现。 |
Object[] |
toArray() |
以正确的顺序(从第一个元素到最后一个元素)返回一个包含此列表中所有元素的数组。 |
---|---|---|
<T> T[] |
toArray(T[] a) |
返回一个数组,该数组按适当顺序(从第一个元素到最后一个元素)包含此列表中的所有元素;返回数组的运行时类型是指定数组的运行时类型。 |
int |
size() |
返回此列表中的元素数。 |
---|---|---|
void |
sort(Comparator<? super E> c) |
根据指定的诱导顺序对列表进行排序 |
链表 LinkedList
同样实现List接口的LinkedList与ArrayList不同,ArrayList是一个动态数组,而LinkedList是一个双向链表。所以它除了有LinkedList适合频繁地对列表进行增加或删除元素操作,因此LinkedList类可用于实现堆栈和队列
public void addFirst(Object o) //在链表头增添元素
public void addLast(Object o) //在链表尾增添元素
public E getFirst() //获取链表首元素
public E getLast() //获取链表尾元素
public Object removeFirst() //删除链表头元素,并返回该元素
public Object removeLast() //删除链表尾元素,并返回该元素
Vector(Stack)
Stack 是Vector的子类, java中Stack只有一个无参构造函数。
属于Stack的方法
push( num) //入栈
pop() //栈顶元素出栈 返回
empty() //判定栈是否为空 注意这里和Collection的区别
peek() //获取栈顶元素
search(num) //栈顶到该元素首次出现的位置的距离
Queue:
Queue 和List 属于同一级,都继承了Collection
//add()和remove(),element()方法在失败的时候会抛出异常(不推荐)
Queue<String> queue = new LinkedList<String>();
offer(object)
poll() // 出队并返回
peek()
isEmpty()//队列为空返回true,否则返回false
size()// 返回队列长度
Deque 用LinkedList 代替使用
PriorityQueue
是Queue接口的实现,可以对其中元素进行排序,
可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类
对于基本数据类型的包装器类,优先队列中元素默认排列顺序是升序排列
但对于自己定义的类来说,需要自己定义比较器
常用方法 和上面Queue一样
小根堆
Queue<Integer> minH = new PriorityQueue<>(); // 小根堆,默认大小为11 相当于 new PriorityQueue<>(11)
Queue<Integer> minH = new PriorityQueue<>(100); // 定义一个默认容量有100的小根堆。在当中增加元素会扩容,只是开始指定大小。不是size,是capacity
大根堆
Queue<Integer> maxH = new PriorityQueue<>((i1, i2) -> i2 - i1); // 大根堆,默认大小为11 相当于 new PriorityQueue<>(11, (i1, i2) -> i2 - i1)
Queue<Integer> maxH = new PriorityQueue<>(100, (i1, i2) -> i2 - i1); // 定义一个默认容量有100的大根堆。在当中增加元素会扩容,只是开始指定大小
PriorityQueue方法(Queue接口方法)
offer
.offer(E e); // 在堆中加入元素e,并调整堆。若成功入堆返回值true,否则返回false --- O(logN)
poll
.poll(); // 弹出堆顶元素,并重新调整堆,返回出队元素e --- O(logN)
peek
.peek(); // 查看堆顶元素, 返回值堆顶元素e --- O(1)
isEmpty
.isEmpty() // 若队空返回true, 否则返回false --- O(1)
size
.size() // 返回队中元素个数 --- O(1)
集合 Set - HashSet
性质:Set中没有重复元素,重复添加的元素抛弃
初始化
默认构造函数
Set<Integer> set = new HashSet<>();
把集合如Stack、Queue、List等Collection作为参数
// List<Integer> list = new ArrayList<>....;
// Set<Integer> set = new HashSet<>(list);HashSet方法(Set接口方法)
方法:add, remove, contains, isEmpty, size
add
.add(E e); // 在集合中添加元素E e, 若成功添加则返回true,若集合中有元素e则返回false --- O(1)
remove
.remove(E e); // 在集合中删除元素e,若删除成功返回true;若集合中没有元素e,返回false --- O(1)
contains
.contains(E e); // 若存在元素e,则返回true,否则返回false --- O(1)
isEmpty
.isEmpty() // 若集合为空返回true, 否则返回false --- O(1)
size
.size() // 返回集合中中元素个数 --- O(1)
first (TreeSet)
.first() // 返回集合里的最小值(若给了比较器从大到小则是返回最大值)
last (TreeSet)
.last() // 返回集合里的最大值(若给了比较器从大到小则是返回最小值)
散列表 HashMap
初始化
<Key, Value> key和value是任何Collection或任何Object
Map<Characters, Integer> map = new HashMap<>();
HashMap方法 (Map接口方法)
put
.put(K key, V value); // 在Map中加入键值对<key, value>。返回value值。如果Map中有key,则replace旧的value --- O(1)
get
.get(K key); // 返回Map中key对应的value。若Map中没有该key,则返回null --- O(1)
getOrDefault
.getOrDefault(K key, V defaultValue); // 返回Map中key对应的value。若Map中没有该key,则返回defaultValue --- O(1)
// For example:
// Map<Character, Integer> map = new HashMap<>();
// if (...) // 如果发现k,则k在Map中的值加1。没一开始没有k,则从0开始加1。(相当于给了key在Map中的一个初试值)
map.put('k', map.getOrDefault('k', 0) + 1);
containsKey
.containsKey(Key key); // 在Map中若存在key,则返回true,否则返回false --- O(1)
containsValue
.containsValue(V value); // 在Map中若存在value,则返回true,否则返回false --- O(1)
keySet
.keySet(); // 返回一个Set,这个Set中包含Map中所有的Key --- O(1)
// For example:
// We want to get all keys in Map
// Map<Character, Integer> map = new HashMap<>();
for (Character key : map.keySet()) {
// Operate with each key
}
values
.values(); // 返回一个Collection<v>,里面全是对应的每一个value --- O(1)
// For example:
// We want to get all values in Map
// Map<Character, Integer> map = new HashMap<>();
for (Integer value : map.values()) {
// Operate with each values
}
isEmpty
.isEmpty() // 若Map为空返回true, 否则返回false --- O(1)
size
.size() // 返回Map中中键值对<K, V>的个数 --- O(1)
字符串
String
初始化
字符串复制初始化
String s = "abc";
基于另外一个字符串
// s = "abc"
String s2 = new String(s);
基于char[]
// s = "abc";
// char[] c = s.toCharArray();
String s3 = new String(c);
// 可以偏移
// public String(char value[], int offset, int count)
String s4 = new String(c, 1, 2); // [offset, offset + count)
// 把char[] 变成字符串
char[] ch = {'a', 'b', 'c'};
String.valueOf(ch);
类方法
String.valueOf( 一个参数Object/基本数据类型 )
返回传入参数obj的toString(),若为空返回字符串"null"。若为基本类型调用其 包装类的toString方法(
Integer.toString(i)
)
String 方法
charAt
.charAt(int index); // 返回index位置的char --- O(1)
length
.length(); // 返回字符串长度 --- O(1)
substring
.substring(int beginIndex, int endIndex); // 返回字符片段[beginIndex, endIndex) --- O(n)
.substring(int beginIndex); // 返回字符片段[beginIndex, end_of_String) 就是从beginIndex开始后面的 ---- O(n)
indexOf 是(暴力查找字符串,不是KMP)
.indexOf(String str) // 返回str第一个出现的位置(int),没找到则返回-1。--- O(m * n) m为原串长度, n为str长度
// (假如要找一个字符char c,str可以表示成String.valueOf(c),然后作为参数传进去.
s.indexOf(String str, int fromIndex); // 同上,但从fromIndex开始找 --- O(m * n)
lastIndexOf
.lastIndexOf(String str); // 返回str最后出现的位置(int),没找到则返回-1。--- O(m * n) m为原串长度, n为str长度
// (假如要找一个字符char c,str可以表示成String.valueOf(c),然后作为参数传进去.
.lastIndexOf(String str, int fromIndex); // 同上,
//但从fromIndex开始从后往前找 [0 <- fromIndex] --- O(m * n)
replace 只能换char
.replace(char oldChar, char newChar); // 返回一个新字符串String,其oldChar全部变成newChar --- O(n)
toCharArray
.toCharArray(); // 返回char[] 数组。把String编程字符数组 --- O(n)
trim 去除前后空格
.trim(); // 返回去除前后空格的新字符串 --- O(n)
split 以什么分开
.split(String regex); // 返回 String[],以regex(正则表达式)分隔好的字符换数组。---- O(n)
// For example
// 从非"/"算起 若"/a/c" -> 会变成"" "a" "c"
String[] date = str.split("/"); // date[0]:1995 date[1]:12 date[2]:18 --- O(n)
复制代码
toLowerCase, toUpperCase 转换大小写
s = s.toLowerCase(); // 返回一个新的字符串全部转成小写 --- O(n)
s = s.toUpperCase(); // 返回一个新的字符串全部转成大写 --- O(n)
技巧
+
连接其他字符串, 但是是两个组成一个新的字符串,有开销。最好用StringBuilder
初始化
StringBuilder sb = new StringBuilder();
instance方法
charaAt
.charAt(int index); // 返回index位置的char --- O(1)
length
.length(); // 返回缓冲字符串长度 --- O(1)
setCharAt
.setCharAt(int index, char ch); // 设置index位置的char为ch --- O(1)
insert
.insert(int offset, String str); // 在offer位置的插入字符串str--- O(m + n)
deleteCharAt
.deleteCharAt(int index); // 删除index位置的char --- O(n)
.deleteCharAt(sb.length() - 1); // 删除最后一个char --- O(1)
delete
.delete(int start, int end); // 删除[start, end)位置的char --- O(n)
reverse
.reverse(); // 反转缓存字符串 --- O(n)
toString
.toString(); // 返回一个与构建起或缓冲器内容相同的字符串 --- O(n)