大家好,我是老三,最近在刷演算法,發現有些api記得不熟,所以整理了一波,如果你也在刷題,趕緊收藏
吧!
集合
在刷題中,各種資料結構是我們常常用到的,例如棧實現迭代、雜湊儲存鍵值對等等,我們來看看常用集合和相關api。
類/介面 | 描述 | 方法 |
---|---|---|
String | 字串 | charAt toCharArray split substring indexOf lastIndexOf replace length |
List | 列表 | add remove get size subList |
Stack | 棧 | push pop peek isEmpty size |
Queue | 佇列 | offer poll peek isEmpty size |
Deque | 雙向佇列 | offerFirst offerLast pollFirst pollLast peekFirst peekLast isEmpty size |
PriorityQueue | 優先佇列 | offer poll peek isEmpty size |
Set | add remove contains isEmpty size first(TreeSet) last(TreeSet) | |
Map | put get getOrDefault containsKey containsValue keySet values isEmpty size |
陣列
陣列就不用多說什麼了,大家最熟悉的資料結構。
Arrays
Arrays是比較常用的陣列工具類,可以完成排序、拷貝等功能。
- 從小到大排序:Arrays.sort(int[] arr)
Arrays.sort(int[] arr, int fromIndex, int toIndex, 比較器); //一定是需要泛型
Arrays.sort(arr, (o1, o2) -> o2 - o1); //陣列全部 從大到小排序 跟Collections.sort()一樣
Arrays.sort(arr, 0, 3, (o1, o2) -> o2 - o1); //從大到小排序,只排序[0, 3)
- 拷貝:Array.copyOf
int[] a = new int[5];
int[] newA = Array.copyOf(a, 5);
列表
列表主要有兩種實現,分別是順序表和連結串列。
順序表本質是一個可以動態擴容的陣列,在Java中的實現是ArrayList
。
連結串列是一個雙向連結串列,Java中連結串列的實現為LinkedList
。LinkedList
在Java中可謂是非常強大的一個集合類,它還可以作為雙向佇列、棧來使用。
注意,ArrayList的擴容需要將舊的陣列的元素複製到新的陣列,時間複雜度為O(n)。
基本方法
- 構造
List<Integer> array = new ArrayList<>(); // 順序表
// Set<Integer> a = new HashSet....
List<Integer> b = new ArrayList<>(a); //接受一個集合容器
- get
get(int index) // 返回元素位置在index的元素e --- array O(1), list O(n)
-
size
size() // 返回陣列/連結串列長度 --- O(1)
- add
add(E e) // 在尾部新增一個元素e --- O(1)
add(int index, E e) // 在index位置插一個元素e --- O(n)
- remove
.remove(int index) // 刪除位於index的元素,並返回刪除元素e --- 刪除最後元素為O(1), 其餘為O(n)
//刪除最後元素 list.remove(list.size() - 1);
- subList
.subList(int from, int to) // 相當於返回原陣列的一個片段,但不要對其進行改動,改動會影響原陣列 --- O(1)
// List<Integer> list, 對原來的list和返回的list做的“非結構性修改”(non-structural changes),
//都會影響到彼此對方. 如果你在呼叫了sublist返回了子list之後,如果修改了原list的大小,那麼之前產生的子list將會失效,變得不可使用
集合工具
Collections是集合工具類,提供了一些操作集合的方法。
- 排序
Collections.sort(list); 從小到大排序
Collections.sort(list, (o1, o2) -> o2 - o1); 從大到小排序, 第二個引數為一個比較器
兩種實現,ArrayList利於查詢,LinkedList利於增刪。
大概對比如下:
操作 | ArrayList | LinkedList |
---|---|---|
get(int index) | O(1) | O(n),平均 n / 4步 |
add(E element) | 最壞情況(擴容)O(n) ,平均O(1) | O(1) |
add(int index, E element) | O(n) ,平均n / 2步 | O(n),平均 n / 4步 |
remove(int index) | O(n) 平均n /2步 | O(n),平均 n / 4步 |
棧
Java中定義了Stack
介面,實現類是Vector
。Vector
是一個祖傳集合類,不推薦使用。
那應該用什麼呢?
Deque
介面實現了完善堆疊操作集合,它有一個我們熟悉的實現類LinkedList
。
- 構造
Deque<Integer> stack=new LinkedList<>();
- push
push(E e); // 入棧元素e, 返回值為元素e --- O(1)
- pop
.pop(); // 出棧一個元素,返回出棧元素e --- O(1)
- peek
peek(); // 檢視棧頂元素, 返回值為棧頂元素e --- O(1)
- isEmpty
isEmpty() // 若棧空返回true, 否則返回false --- O(1)
- size
size() // 返回棧中元素個數 --- O(1)
佇列
佇列s是一種先進先出的結構,在Java中的介面定義是Queue
,具體實現還是我們的老朋友LinkedList
。
- 構造
Queue<Integer> q = new LinkedList<>();
- offer
offer(E e); // 隊尾加入元素e。 若成功入隊返回值true,否則返回false --- O(1)
- poll
poll(); // 出隊頭,返回出隊元素e --- O(1)
- peek
peek(); // 檢視隊頭元素, 返回值隊首元素e --- O(1)
- isEmpty
isEmpty() // 若隊空返回true, 否則返回false --- O(1)
- size
size() // 返回隊中元素個數 --- O(1)
雙向佇列
Queue
有一個子介面Dueue
,即雙向佇列,和單向佇列不同,它的出隊入隊可以從兩個方向。
- 構造
Dueue<Integer> q = new LinkedList<>();
- offFirst
offFirst(Object e) // 將指定元素新增到雙端佇列的頭部 --- O(1)
- offLast
offLast(Object e) //將指定元素新增到雙端佇列的尾部 --- O(1)
- pollFirst
pollFirst() //獲取並刪除雙端佇列的第一個元素 --- O(1)
- pollLast
pollLast() //獲取並刪除雙端佇列的最後一個元素 --- O(1)
- peekFirst
peekFirst() //獲取但不刪除雙端佇列的第一個元素 --- O(1)
- peekLast
peekLast() //獲取但不刪除雙端佇列的最後一個元素 --- O(1)
優先佇列
優先佇列是一種比較特殊的佇列,儲存佇列元素的順序不是按照元素新增的順序來儲存的,而是在新增元素的時候對元素的大小排序後再儲存。
所以在隊頭的元素不是按照先後順序,而是按照大小順序。
在Java中的實現是PriorityQueue
,底層是一棵樹, 以小根堆為例。對於任意結點來說,該節點的值比其左右孩子的值都要小。 (就是最上面的結點最小)。 大根堆類似,最上面結點最大
- 構造
- 小根堆
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的大根堆。在當中增加元素會擴容,只是開始指定大小
- offer
offer(E e); // 在堆中加入元素e,並調整堆。若成功入堆返回值true,否則返回false --- O(logN)
- poll
poll(); // 彈出堆頂元素,並重新調整堆,返回出隊元素e --- O(logN)
- peek
peek(); // 檢視堆頂元素, 返回值堆頂元素e --- O(1)
雜湊表
雜湊表示一種<key,value>型的資料結構,在Java中的實現是HashMap
。
- 構造
Map<Characters, Integer> map = new HashMap<>();
- 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)
get(x) == null // 可以代替改用法
- 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)
Set
Set是一種沒有重複元素的集合,常用的實現是HashSet
。
- 構造
Set<Integer> set = new HashSet<>();
List<Integer> list = new ArrayList<>....;
Set<Integer> set = new HashSet<>(list);
- 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
first() // 返回集合裡的最小值(若給了比較器從大到小則是返回最大值)
- last
last() // 返回集合裡的最大值(若給了比較器從大到小則是返回最小值)
字串
String
不可變數(相當於只讀final修飾),每個位置元素是個char。
- 初始化
字串複製初始化
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);
- 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
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
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
由於String是所謂的不可變類,使用 str+
這種形式拼接字串實際上,是JVM幫助迴圈建立StringBuilder來拼接,所以拼接字串最好用StringBuilder。
- 構造
StringBuilder sb = new StringBuilder();
- charAt
charAt(int index); // 返回index位置的char --- O(1)
- length
length(); // 返回緩衝字串長度 --- O(1)
- apped
append(String str) // 拼接字串 --- O(n)
- toString
toString(); // 返回一個與構建起或緩衝器內容相同的字串 --- O(n)
數學
最大最小值
在一些題目裡,需要用到最大,最小值,Java中各個資料型別的最大最小值定義如下:
fmax = Float.MAX_VALUE;
fmin = Float.MIN_VALUE;
dmax = Double.MAX_VALUE;
dmin = Double.MIN_VALUE;
bmax = Byte.MAX_VALUE;
bmin = Byte.MIN_VALUE;
cmax = Character.MAX_VALUE;
cmin = Character.MIN_VALUE;
shmax = Short.MAX_VALUE;
shmin = Short.MIN_VALUE;
imax = Integer.MAX_VALUE;
imin = Integer.MIN_VALUE;
lmax = Long.MAX_VALUE;
lmin = Long.MIN_VALUE;
Math
- max
Math.max(long a, long b); //返回兩個引數中較大的值
- sqrt
Math.sqrt(double a); //求引數的算術平方根
- abs
Math.abs(double a); //返回一個型別和引數型別一致的絕對值
- pow
Math.pow(double a, double b); //返回第一個引數的第二個引數次方。
- ceil
Math.ceil(double x); //向上取整
- floor
Math.floor(double x); //向下取整
- round
Math.round(double x); //四捨五入
"簡單的事情重複做,重複的事情認真做,認真的事情有創造性地做!"——
我是
三分惡
,一個能文能武的全棧開發。
點贊
、關注
不迷路,我們們下期見!
參考:
[1].Java刷題常用API
[2].Java 刷題集合類