要求当用户在浏览器的地址栏输入地址时,浏览器能够根据用户输入的历史记录对用户现在的输入进行匹配,提示用户可能要输入的字符。大概意思就是要实现和现在浏览器差不多的效果,比如用户之前输入过aaa,abcd,abcc(简化以下,不考虑前缀”www.”和后缀”.com”),当用户再次在浏览器地址栏输入a时,系统能够提示aaa,aaaa,abcd,abcc。输入ab时,系统能够提示abcd,abcc。
思路:感觉可以用树的结构解决该问题,解决过程如下:
1.数据结构选择
用户输入aaa,aaaa,abcd,abcc,后,内部存储结构为:
树的数据结构为:
class Tree {
Tree tParent;
char val;
boolean flag;
List<Tree> children;
Tree(Tree p, char c, boolean b) {
tParent = p;
val = c;
flag = b;
children = new ArrayList<Tree>();
}
}
其中flag用于表明是否至此为止可得到一条路径。
2.建树过程。
用户输入aaa,aaaa,abcd,abcc,后,树的变化过程如下图所示:
图V即为存储历史数据aaa&aaaa&abcd&abcc后的最终结果,其中黄色节点即表示flag=true,表明输入的历史数据中存有一条历史数据到黄色节点为止。
3.搜索过程。
以用户输入aa&ac为例。输入aa后,系统在树中找到符号条件的点(即图中红色节点)。以该节点为根遍历,以黄色的点为结尾,即可得到a&aa。加上前缀,即得到最终结果:aaa、aaaa。输入ac后,无法在树中找到ac,因此无提示
4.CODE:
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
class Tree {
Tree tParent;
char val;
boolean flag;
List<Tree> children;
Tree(Tree p, char c, boolean b) {
tParent = p;
val = c;
flag = b;
children = new ArrayList<Tree>();
}
}
public class Solution {
/**
* 向root中插入节点,返回插入的节点。插入过程中注意flag的设置
*
* @param root
* @param c
* @param b
* @return
*/
public static Tree insert(Tree root, char c, boolean b) {
Tree node = new Tree(root, c, b);
if (!isContain(root.children, node)) {
root.children.add(node);
} else {
for (Tree temp : root.children)
if (temp.val == node.val) {
if (b == true)
temp.flag = b;
return temp;
}
}
return node;
}
/**
* 判断children中是否已存在node
*
* @param children
* @param node
* @return
*/
public static boolean isContain(List<Tree> children, Tree node) {
for (Tree temp : children) {
if (temp.val == node.val)
return true;
}
return false;
}
/**
* 打印以node为根节点的路径
*
* @param node
*/
public static void printPath(Tree node) {
Queue<Tree> queue = new ArrayDeque<Tree>();
Tree temp = new Tree(null, '.', false);
queue.add(node);
while (queue.size() != 0) {
temp = queue.poll();
if (temp.flag == true) {
Tree ori = new Tree(null, ',', false);
ori = temp;
String strTemp = "";
while (temp.tParent != null) {
strTemp += temp.val;
temp = temp.tParent;
}
for (int i = strTemp.length() - 1; i >= 0; --i)
System.out.print(strTemp.charAt(i));
System.out.println();
temp = ori;
}
for (Tree t : temp.children)
queue.add(t);
}
}
/**
* 查找&遍历
*
* @param root
* @param str
*/
public static void SendHint(Tree root, String str) {
Tree node = searchNode(root, str);
if (node == null) {
System.out.println("No Hint");
return;
}
printPath(node);
}
/**
* 根据输入的string在历史树中进行查找,找到符合条件的节点返回(对该节点进行遍历即可得到最终提示)
*
* @param root
* @param str
* @return
*/
public static Tree searchNode(Tree root, String str) {
if (str == null || str.length() == 0)
return root;
for (int i = 0; i < str.length(); ++i) {
for (Tree node : root.children) {
if (node.val == str.charAt(i)) {
return searchNode(node, str.substring(i + 1, str.length()));
}
}
}
return null;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Tree origin = new Tree(null, '.', false);
Tree root = new Tree(null, '.', false);
origin = root;
String[] str = { "aaa", "aaaa", "abcd", "abcc", "adbc", "adddd" };
// 建树
for (String temp : str) {
for (int i = 0; i < temp.length(); ++i) {
root = insert(root, temp.charAt(i), (i == temp.length() - 1));
}
root = origin;
}
// 搜索
SendHint(origin, "ab");
}
}