锁定老帖子 主题:两个大数据量处理的问题.被鄙视了呜呜
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-09-13
tmj_159 写道 第一题 hash 到小文件,统计到小文件,将小文件归并排序
根据词的拼音首字母 分26个文件存 ? |
|
返回顶楼 | |
发表时间:2011-09-13
Reset 写道 tmj_159 写道 第一题 hash 到小文件,统计到小文件,将小文件归并排序
根据词的拼音首字母 分26个文件存 ? 不一定固定按照第首字母,也可以按前N个字母或任意段。或者使用多级小文件。 当数据量比内存大的时候,必然要转储的。剩下的解决的就是转储时查找的效率问题。 |
|
返回顶楼 | |
发表时间:2011-09-13
第二个你都会了 第一个为什么你不会呢?用正则呀··当初笔试也遇到过这个类似的题,印象比较深。
|
|
返回顶楼 | |
发表时间:2011-09-13
可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树. 得到这个树后可以遍历这颗树来比较频率最高的单词. A / \ B C / \ C D |
|
返回顶楼 | |
发表时间:2011-09-14
1亿个词扔到数据库里,select count order by 一下就出来了
|
|
返回顶楼 | |
发表时间:2011-09-14
最后修改:2011-09-14
cdcx 写道 可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树. 得到这个树后可以遍历这颗树来比较频率最高的单词. A / \ B C / \ C D 很靠谱,+1,尝试着实现了一下 public class WordTree { public static void main(String[] args) { WordTree t = new WordTree(); String[] ss = {"asdf", "asdf", "as", "a"}; for(String s : ss) { t.accept(s); } CharNode cNode = t.getMaxNode(); System.out.println(cNode.num + " : " + cNode.getS()); } /** * 接收并处理一条新纪录 * @author lzxz * @param s */ public void accept(String s) { this.accept((CharSequence)s.toUpperCase()); } /** * 得到最大数量节点 * @author lzxz * @return */ public CharNode getMaxNode() { int maxNum = 0; CharNode maxNode = null; for(CharNode cNode : list) { if(cNode.num > maxNum) { maxNode = cNode; maxNum = cNode.num; } } return maxNode; } /** * 得到最大数量节点,要求必须全部大写 * @author lzxz * @param cs */ public void accept(CharSequence cs){ this.root.accept(cs); } private CharNode root = new CharNode(null, '$'); private final List<CharNode> list = new ArrayList<CharNode>(); private class CharNode { private char c; private int num; private CharNode parent = null; private Map<Character, CharNode> next; /** * 得到到达本路径的字符串全量 * @author lzxz * @return */ private String getS() { if(this.parent == null) { return String.valueOf(c); } return this.parent.getS() + c; } /** * 接收并处理一条新纪录 * @author lzxz * @param cs */ private void accept(CharSequence cs) { CharNode node = next.get(cs.charAt(0)); if(node == null) { node = new CharNode(this, cs.charAt(0)); next.put(cs.charAt(0), node); list.add(node); } if(cs.length() == 1){ node.num ++; } else { node.accept(cs.subSequence(1, cs.length())); } } /** * 指定参数构造CharNode实例。 * @param parent * @param c */ public CharNode(CharNode parent, char c){ num = 0; this.parent = parent; this.c = c; next = new HashMap<Character, CharNode>(); } } } |
|
返回顶楼 | |
发表时间:2011-09-14
oaklet 写道 1亿个词扔到数据库里,select count order by 一下就出来了
数据库没那么强,1亿条记录order by指不定得跑几个小时呢 |
|
返回顶楼 | |
发表时间:2011-09-14
像lucene里面的记录方式就是 1. 分词 2.把对应的词条加入文档,文档里面会记录对应的词的索引条数, 如果真正意义来说要去实时统计的话,不是通过计算,而是直接读取词条记录的条数。
|
|
返回顶楼 | |
发表时间:2011-09-14
lzxz1234 写道 cdcx 写道 可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树. 得到这个树后可以遍历这颗树来比较频率最高的单词. A / \ B C / \ C D 很靠谱,+1,尝试着实现了一下 public class WordTree { public static void main(String[] args) { WordTree t = new WordTree(); String[] ss = {"asdf", "asdf", "as", "a"}; for(String s : ss) { t.accept(s); } CharNode cNode = t.getMaxNode(); System.out.println(cNode.num + " : " + cNode.getS()); } /** * 接收并处理一条新纪录 * @author lzxz * @param s */ public void accept(String s) { this.accept((CharSequence)s.toUpperCase()); } /** * 得到最大数量节点 * @author lzxz * @return */ public CharNode getMaxNode() { int maxNum = 0; CharNode maxNode = null; for(CharNode cNode : list) { if(cNode.num > maxNum) { maxNode = cNode; maxNum = cNode.num; } } return maxNode; } /** * 得到最大数量节点,要求必须全部大写 * @author lzxz * @param cs */ public void accept(CharSequence cs){ this.root.accept(cs); } private CharNode root = new CharNode(null, '$'); private final List<CharNode> list = new ArrayList<CharNode>(); private class CharNode { private char c; private int num; private CharNode parent = null; private Map<Character, CharNode> next; /** * 得到到达本路径的字符串全量 * @author lzxz * @return */ private String getS() { if(this.parent == null) { return String.valueOf(c); } return this.parent.getS() + c; } /** * 接收并处理一条新纪录 * @author lzxz * @param cs */ private void accept(CharSequence cs) { CharNode node = next.get(cs.charAt(0)); if(node == null) { node = new CharNode(this, cs.charAt(0)); next.put(cs.charAt(0), node); list.add(node); } if(cs.length() == 1){ node.num ++; } else { node.accept(cs.subSequence(1, cs.length())); } } /** * 指定参数构造CharNode实例。 * @param parent * @param c */ public CharNode(CharNode parent, char c){ num = 0; this.parent = parent; this.c = c; next = new HashMap<Character, CharNode>(); } } } 这个问题我也考虑过.. 但是怕出现如下场景 用户查询100次中国 然后用户查询了100000次中国人 于是中国就变成100100次了 |
|
返回顶楼 | |
发表时间:2011-09-14
ansjsun 写道 lzxz1234 写道 cdcx 写道 可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树. 得到这个树后可以遍历这颗树来比较频率最高的单词. A / \ B C / \ C D 很靠谱,+1,尝试着实现了一下 public class WordTree { public static void main(String[] args) { WordTree t = new WordTree(); String[] ss = {"asdf", "asdf", "as", "a"}; for(String s : ss) { t.accept(s); } CharNode cNode = t.getMaxNode(); System.out.println(cNode.num + " : " + cNode.getS()); } /** * 接收并处理一条新纪录 * @author lzxz * @param s */ public void accept(String s) { this.accept((CharSequence)s.toUpperCase()); } /** * 得到最大数量节点 * @author lzxz * @return */ public CharNode getMaxNode() { int maxNum = 0; CharNode maxNode = null; for(CharNode cNode : list) { if(cNode.num > maxNum) { maxNode = cNode; maxNum = cNode.num; } } return maxNode; } /** * 得到最大数量节点,要求必须全部大写 * @author lzxz * @param cs */ public void accept(CharSequence cs){ this.root.accept(cs); } private CharNode root = new CharNode(null, '$'); private final List<CharNode> list = new ArrayList<CharNode>(); private class CharNode { private char c; private int num; private CharNode parent = null; private Map<Character, CharNode> next; /** * 得到到达本路径的字符串全量 * @author lzxz * @return */ private String getS() { if(this.parent == null) { return String.valueOf(c); } return this.parent.getS() + c; } /** * 接收并处理一条新纪录 * @author lzxz * @param cs */ private void accept(CharSequence cs) { CharNode node = next.get(cs.charAt(0)); if(node == null) { node = new CharNode(this, cs.charAt(0)); next.put(cs.charAt(0), node); list.add(node); } if(cs.length() == 1){ node.num ++; } else { node.accept(cs.subSequence(1, cs.length())); } } /** * 指定参数构造CharNode实例。 * @param parent * @param c */ public CharNode(CharNode parent, char c){ num = 0; this.parent = parent; this.c = c; next = new HashMap<Character, CharNode>(); } } } 这个问题我也考虑过.. 但是怕出现如下场景 用户查询100次中国 然后用户查询了100000次中国人 于是中国就变成100100次了 不好意思我仔细看了下代码..仿佛是实现了..我没有考虑可以回溯..不过内存占用率应该还是比较高的...但是还是比较靠谱的...我之前认为实现的办法是..先hash后存入map...key是单词..value是数量.... 最后迭代出结果..不过貌似你这个比较好.我试试哈 |
|
返回顶楼 | |