N皇后和數獨問題比較難,暫時不去練習。
1. 題目
- 實現一個求解平方根的函數:實現 int sqrt(int x)函數,計算並返回x的平方根,其中x是非負整數。
- 實現一個字典樹,包含insert, search,startsWith這三個操作。
2. 基本知識
2.1 二分查找
2.1.1 前提條件:
- sorted(單調遞增或者遞減)
- 存在上下界
- 能夠通過索引來訪問
2.1.2 適用場景:
有序的數組;鏈表不適合
2.2 字典樹
2.2.1 定義
Trie樹,即字典樹,又稱單詞查找樹或鍵樹,是一種樹形結構,是哈希樹的變種。典型的應用是用於統計和排序大量的字符串,所以經常被搜索引擎系統用於文本詞頻統計。
2.2.2 優點
最大限度的減少無謂的字符串比較,查詢效率比哈希表高。
2.2.3 核心思想
Trie的核心思想是空間換時間,利用字符串的公共前綴來降低查詢時間的開銷,以達到提高效率的目的。
2.2.4 基本性質
- 根節點不包含字符,除根節點外每一個節點都只包含一個字符
- 從根節點到某一節點,路徑上經過的字符連接起來,爲該節點對應的字符
- 每個節點的所有子節點包含的字符不同
3. 算法題解
3.1 實現一個求解平方根的函數
實現 int sqrt(int x)函數,計算並返回x的平方根,其中x是非負整數
解法:二分查找
此題求解並不是精確值,所以可以這麼做,首先確定邊界:根據常識定義邊界,非負數,左邊界爲1,右邊界肯定不大於n/2,然後進行二分查找,直到left == right或者left > right時截止,將left值作爲題解。(向下取整)
時間複雜度 O(logn),空間複雜度 O(1)
public static int mySqurt(int n) {
//根據常識定義邊界,非負數,左邊界爲1,右邊界肯定不大於n/2
int left = 1;
int right = n/2;
//只要還左邊界比右邊界小,一直循環
while (left < right) {
// 進行二分查找
int mid = left + (right - left)/2;
int square = mid * mid;
if (square > n) {
right = mid - 1;
}else {
left = mid;
}
}
return left;
}
3.2 實現一個字典樹,包含insert, search,startsWith這三個操作
說明:
- 假設所有輸入都是小寫字母a-z
- 保證所有輸入均爲非空字符串
首先,定義TrieNode類:
public class TrieNode {
private TrieNode[] links;
private boolean isEnd;
public TrieNode(){
links = new TrieNode[26];
}
public boolean contaionsKey(char cha){
return links[cha - '1'] != null;
}
public TrieNode get(char cha){
return links[cha - 'a'];
}
public void put(char cha, TrieNode node){
links[cha - 'a'] = node;
}
public boolean isEnd() {
return isEnd;
}
public void setEnd() {
isEnd = true;
}
}
插入字符串
遍歷字符串,層層判斷是否已有該字符,如果沒有,則創建一個新節點,存入字符,如果已有,則移動到樹的下一層繼續遍歷。
時間複雜度:O(n), 空間複雜度 O(n)(如果節點都不存在的情況,需要創建n次節點)
public class Trie {
private TrieNode root;
public Trie(){
root = new TrieNode();
}
public void insert(String word){
TrieNode node = root;
for (int i = 0; i< word.length(); i++) {
char c = word.charAt(i);
if (!node.contaionsKey(c)) {
node.put(c, node);
}
node = node.get(c);
node.setEnd();
}
}
}
查找字符串是否存在
遍歷字符串中的字符,如果Trie中已存在字符,移動到下一個節點繼續查找,直到最後一個char找到爲止,否則返回false。
時間複雜度 O(n) 空間複雜度O(1)
public boolean sarch(String word){
TrieNode node = root;
for (int i = 0; i < word.length(); i ++){
char c = word.charAt(i);
if (node.contaionsKey(c)){
node = node.get(c);
}else{
node = null;
break;
}
}
if (node != null && node.isEnd()){
return true;
}else {
return false;
}
}