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