day 14-15 算法:二分查找、字典樹;實現一個求解平方根的函數,實現一個字典樹

N皇后和數獨問題比較難,暫時不去練習。

1. 題目

  1. 實現一個求解平方根的函數:實現 int sqrt(int x)函數,計算並返回x的平方根,其中x是非負整數。
  2. 實現一個字典樹,包含insert, search,startsWith這三個操作。

2. 基本知識

2.1 二分查找

2.1.1 前提條件:

  1. sorted(單調遞增或者遞減)
  2. 存在上下界
  3. 能夠通過索引來訪問

2.1.2 適用場景:

有序的數組;鏈表不適合

2.2 字典樹

2.2.1 定義

Trie樹,即字典樹,又稱單詞查找樹或鍵樹,是一種樹形結構,是哈希樹的變種。典型的應用是用於統計和排序大量的字符串,所以經常被搜索引擎系統用於文本詞頻統計。

2.2.2 優點

最大限度的減少無謂的字符串比較,查詢效率比哈希表高。

2.2.3 核心思想

Trie的核心思想是空間換時間,利用字符串的公共前綴來降低查詢時間的開銷,以達到提高效率的目的。

2.2.4 基本性質

  1. 根節點不包含字符,除根節點外每一個節點都只包含一個字符
  2. 從根節點到某一節點,路徑上經過的字符連接起來,爲該節點對應的字符
  3. 每個節點的所有子節點包含的字符不同

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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章