算法28--统计文本中出现次数最多的单词(字典树)

统计一个文本中,出现次数最多的单词:单词全部小写,单词与单词之间以空格间隔

1.利用字典  key为单词  value为单词出现的次数

def mostString():
    dict = {}
    fr = open('preprocessing.txt')
    k = 0
    n = 0
    for line in fr.readlines():
        for s in line.strip().split(' '):
            if s not in dict.keys():
                dict[s] = 0
            else:
                dict[s] = dict[s] + 1
            if dict[s]>=n:
                k = s
                n = dict[s]
    #print(dict)
    print(k)

代码如上,利用一个字典来保存所有字典,value来保存每个单词的次数,当字典中没有该单词时,执行新增操作;若已经有该单词则执行更新操作,最后返回次数最多的单词即可。空间复杂度N  时间复杂度平均为N

2.字典树解法

字典树,又称为单词查找树,Tire数,是一种树形结构,它是一种哈希树的变种。

基本性质如下:

  • 根节点不包含字符,除根节点外的每一个子节点都包含一个字符
  • 从根节点到某一节点。路径上经过的字符连接起来,就是该节点对应的字符串
  • 每个节点的所有子节点包含的字符都不相同

典型应用是用于统计,排序和保存大量的字符串(不仅限于字符串),经常被搜索引擎系统用于文本词频统计。

利用字符串的公共前缀来减少查询时间,最大限度的减少无谓的字符串比较,查询效率比哈希树高。

       如果文本中的单词数量很多,并且大部分单词前缀都相同,那么利用第一种字典方式来保存所有单词,则会浪费许多空间,此时可以利用字典树来保存单词,充分利用最大公共前缀。

构造字典树节点:

class TrieNode:
    def __init__(self, var=None, parent=None, num=0):
        self.num = num
        self.isEnd = False
        self.son = {}
        self.var = var
        self.parent = parent

num  该字符在某种前缀中出现的次数

isEnd  true标识某个单词以该字符结尾

var  该节点保存的字符

son 该节点所有叶子节点

parent  指向父节点的指针

1.构造函数:

root = None
    
    def __init__(self):
        self.root = TrieNode()

2.在字典树中插入一个单词:

def insert(self, str):
        if len(str)<=0:
            return
        node = self.root    
        for c in str:
            if c not in node.son.keys():
                node.son[c] = TrieNode(c, node, 1)                
            else:
                node.son[c].num += 1
            node = node.son[c]
        node.isEnd = True

遍历单词的每个字符,找到从根节点开始的一条路径来保存所有字符,若字符不存在则新建一个节点,若已经存在则更新计数,最后将单词最后一个字符指示变量isEnd置为true

2.在字典树中查询一个单词是否存在

def has(self, str):
        if len(str)==0:
            return False
        node = self.root    
        for c in str:
            if c not in node.son.keys():
                return False
            else:
                node = node.son[c]
        return node.isEnd

从字典树的根节点开始,依次匹配单词的每个字符,若最终存在某条路径包含该单词所有字符,则观察最后一个字符的指示变量

3.计算以某个字符为前缀的所有单词总数

def countPrefix(self, prefix):
        if len(prefix)==0:
            return -1
        node = self.root
        for c in prefix:
            if c not in node.son.keys():
                return 0
            else:
                node = node.son[c]
        return node.num

找到该字符串的最后一个字符位置,返回计数值即可。

4.遍历字典树

def preOrder(self, node):
        if node != None:
            print (list(node.son.keys()))
            for child in node.son.keys():
                self.preOrder(node.son[child])

5.计算出现次数最多的单词

def mostString(self):
        max = [0]
        r = [TrieNode()]
        self.helper(self.root, max, r)
        x = r[0]
        print(x)
        s = []
        while x!=None:
            s.append(x.var)
            x = x.parent
        s.reverse()
        return s

    def helper(self, node, max, r):
        if node != None:
            print (node.num, node.isEnd)
            if node.isEnd and node.num >= max[0]:
                r[0] = node
                max[0] = node.num
            print('r value ', max, r[0].var)
            for child in node.son.keys():
                self.helper(node.son[child], max, r)

如上所示,遍历每一个节点,找到那些指示变量isEnd==true并且计数值最大的节点,从该节点沿parent指针回溯到根节点,然后倒序输出即可。

def mostString2():
    dict = {}
    t = Trie()
    fr = open('preprocessing.txt')    
    for line in fr.readlines():
        for s in line.strip().split(' '):
            print(s) 
            t.insert(s)
    #print(t.preOrder(t.root))
    #print(t)
    #t.preOrder(t.root)
    #print(k)
    print(t.has('chen'))   
    print(t.has('chendsfdsfsd'))
    print(t.countPrefix('chen'))  
    print(t.mostString())

问题:

1.python中是否支持对象数组,本来想利用对象数组来保存某节点的孩子节点集合的

2.python中参数传递问题,为求最大值,函数传递时使用max=[0] r=[TrieNode()],很别扭

max=0属于不可变对象可以理解,但是r=TrieNode() r应该是可变对象吧,但是这里好像也是不可改变的

测试一下:

def canchange(r):
    r = TrieNode(2) 
    print('func inner ',r.var)    
                
def mostString2():
    dict = {}
    t = Trie()
    fr = open('preprocessing.txt')    
    for line in fr.readlines():
        for s in line.strip().split(' '):
            print(s) 
            t.insert(s)
    #print(t.preOrder(t.root))
    #print(t)
    #t.preOrder(t.root)
    #print(k)
    print(t.has('chen'))   
    print(t.has('chendsfdsfsd'))
    print(t.countPrefix('chen'))  
    print(t.mostString())
    r = TrieNode(1)
    print('before',r.var)
    canchange(r)
    print('after',r.var)

可知对象指针是不可变对象,函数传递属于值传递,好奇怪!

参考地址:

https://www.cnblogs.com/xujian2014/p/5614724.html

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在 Java ,可以使用 HashMap 来统计整数序列每个数出现次数,最后遍历 HashMap 找到出现次数最多的数即可。代码示例: ``` import java.util.HashMap; public class Main { public static void main(String[] args) { int[] nums = {1, 2, 3, 4, 1, 1, 2}; HashMap<Integer, Integer> map = new HashMap<>(); for (int num : nums) { if (map.containsKey(num)) { map.put(num, map.get(num) + 1); } else { map.put(num, 1); } } int maxNum = 0, maxCount = 0; for (int num : map.keySet()) { if (map.get(num) > maxCount) { maxNum = num; maxCount = map.get(num); } } System.out.println("整数序列出现次数最多的数是:" + maxNum); } } ``` ### 回答2: 要求找出整数序列出现次数最多的数,可以使用Java语言编写一个算法来实现。 首先,我们可以使用HashMap来统计整数序列每个数出现次数。遍历整数序列,对于遍历到的数字,如果在HashMap已经存在,就将对应的计数器加1;如果不存在,就将该数字作为键添加到HashMap,并将对应的计数器初始化为1。 在完成HashMap的统计后,我们需要遍历一次HashMap,找出出现次数最多的数。可以使用两个变量maxCount和maxNum来保存当前出现次数最多的数字和对应的次数。遍历HashMap,对于每一个键值对,如果该键对应的计数器大于maxCount,就更新maxCount和maxNum。最终,maxNum就是整数序列出现次数最多的数。 下面是使用Java代码实现的示例: ```java import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) { int[] sequence = {1, 2, 3, 4, 4, 2, 2, 3, 3, 3}; int maxNum = findMostFrequentNumber(sequence); System.out.println("出现次数最多的数是:" + maxNum); } public static int findMostFrequentNumber(int[] sequence) { Map<Integer, Integer> countMap = new HashMap<>(); for (int num : sequence) { if (countMap.containsKey(num)) { countMap.put(num, countMap.get(num) + 1); } else { countMap.put(num, 1); } } int maxCount = 0; int maxNum = 0; for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) { int num = entry.getKey(); int count = entry.getValue(); if (count > maxCount) { maxCount = count; maxNum = num; } } return maxNum; } } ``` 以上代码输出的结果为:出现次数最多的数是:3。 ### 回答3: 要求解整数序列出现次数最多的数,可以通过以下步骤实现: 1. 建立一个HashMap,用于存储整数和它出现次数。 2. 遍历整数序列,将每个整数作为key,出现次数作为value,存入HashMap。 3. 定义一个变量maxCount,用于记录出现次数最多的数的次数。 4. 定义一个变量mostFrequent,用于记录出现次数最多的数。 5. 遍历HashMap,比较每个整数出现次数和maxCount的大小。 - 如果当前整数出现次数大于maxCount,将当前整数的次数赋值给maxCount,并将当前整数赋值给mostFrequent。 - 如果当前整数出现次数等于maxCount,将当前整数添加到mostFrequent。 6. 输出mostFrequent,即为整数序列出现次数最多的数。 以下是一个用Java实现的例子: ```java import java.util.HashMap; public class Main { public static void main(String[] args) { int[] nums = {1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5}; HashMap<Integer, Integer> countMap = new HashMap<>(); // 统计每个整数的出现次数 for (int num : nums) { countMap.put(num, countMap.getOrDefault(num, 0) + 1); } int maxCount = 0; // 找出出现次数最多的数 for (int num : countMap.keySet()) { int count = countMap.get(num); if (count > maxCount) { maxCount = count; } } System.out.println("出现次数最多的数是:"); for (int num : countMap.keySet()) { int count = countMap.get(num); if (count == maxCount) { System.out.println(num); } } } } ``` 输出结果为: ``` 出现次数最多的数是: 5 ``` 通过HashMap统计每个整数的出现次数,然后遍历HashMap找到出现次数最多的数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值