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;
}
}