出现次数最多的数

一、【LeetCode 501】二叉搜索树中的众数

1. 题目描述

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

例如:
给定 BST [1,null,2,2],

   1
    \
     2
    /
   2

返回[2].

提示: 如果众数超过1个,不需考虑输出顺序

2. 解题思路

核心思想:中序遍历 + 哈希表
同样是利用二叉搜索树的中序遍历是升序序列的性质,可以方便统计。还利用哈希表防止重复的性质。
(1)利用哈希表将节点值和其出现的次数建立映射。每遍历到一个节点,就判断当前节点的值是否在哈希表中。若不在就将其出现的次数置为1;若存在,就将出现的次数+1;
(2)完成遍历后得到了键值对是节点值和其出现次数的哈希表。这时就可以利用sorted()函数将哈希表按照value值进行排序list = sorted(hash_map.items(), key = lambda item:item[1])
(3)初始化一个新数组 result,用来存放众数。排序之后的列表中最后一个元组肯定是出现次数最多的键值对,可将该元组的第一个元素添加到新数组 result 中;然后倒序遍历排序完的列表 listfor i in range(len(list)-2, -1, -1)(从倒数第二个元组开始),依次将每个元组的第二个元素与最后一个元组的第二个元素进行比较看是否相等,若相等,则将对应元组的第一个元素添加进 result 中;若不相等,直接break跳出整个循环体结束循环,然后返回 result 即为所得。

3. 代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findMode(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        hash_map = {}
        stack = []
        node = root
        while stack or node:
            while node:
                stack.append(node)
                node = node.left
            node = stack.pop()
            if node.val not in hash_map:
                hash_map[node.val] = 1
            else:
                hash_map[node.val] += 1
            node = node.right
        list = sorted(hash_map.items(), key = lambda item:item[1])
        result = [list[-1][0]]
        for i in range(len(list)-2, -1, -1):           
            if list[-1][1] == list[i][1]:
                result.append(list[i][0])
            else:
                break            
        return result

二、【LeetCode 508】出现次数最多的子树元素和

1. 题目描述

给出二叉树的根,找出出现次数最多的子树元素和。一个结点的子树元素和定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。然后求出出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的元素(不限顺序)。

示例 1
输入:

  5
 /  \
2   -3

返回 [2, -3, 4],所有的值均只出现一次,以任意顺序返回所有值。

示例 2
输入:

  5
 /  \
2   -5

返回 [2],只有 2 出现两次,-5 只出现 1 次。

提示: 假设任意子树元素和均可以用 32 位有符号整数表示。

2. 题解思路

核心思想:DFS(后序遍历)+ 哈希表
因为要计算子树元素和,所以使用自底向上的递归可以避免重复计算。依旧是将得到的元素和与其出现的次数建立映射存在哈希表中。

  • 首先是定义一个辅助函数DFS用来后序遍历递归计算子树元素和。【一个递归小白的反思:递归函数要有返回值,才能在调用时用变量去接收,例:left = self.DFS(hash_map, root.left),如果没有返回值return sum,这样做的意义何在?】,使用递归可认为已经得到了结果,即先得到左子树的元素和 left, 再得到右子树的元素和 right,最后将left与right相加再加上根节点的值就可认为得到了一棵小树的元素和。
  • 像上题一样将得到的元素和存入哈希表建立映射,在主函数中调用DFS函数即可得到该哈希表,再后面的做法就与上题一模一样了。

3. 代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
        if not root:
            return
        hash_map = {}
        self.DFS(hash_map, root)
        list = sorted(hash_map.items(), key = lambda item:item[1])
        result = [list[-1][0]]
        for i in range(len(list)-2, -1, -1):
            if list[-1][1] == list[i][1]:
                result.append(list[i][0])
            else:
                break
        return result

    def DFS(self, hash_map, root):
        if not root:
            return 0
        left = self.DFS(hash_map, root.left)
        right = self.DFS(hash_map, root.right)
        sum = left + right + root.val
        if sum not in hash_map:
            hash_map[sum] = 1
        else:
            hash_map[sum] += 1
        return sum

三、补充知识(sort函数的那些事)

  • sort() 是Python列表的一个内置的排序方法,list.sort() 方法排序时直接修改原列表,返回None;重要的是:sort() 只是列表的一个方法,只适用于列表。
  • sorted() 是Python内置的一个排序函数,它会从一个迭代器返回一个排好序的新列表。而sorted() 函数接受一切迭代器,返回新列表。

相比于 sort(),sorted() 使用的范围更为广泛,但是如果不需要保留原列表,sort更有效一点。
sort()方法只有列表才有,集合,字典,元组都没有sort()方法。 所以上述题目在对字典进行排序时用到的是sorted()方法。

以下引用是菜鸟教程的官方定义:

sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

1. sorted()函数的语法

语法:sorted(iterable, key=None, reverse=False)
参数说明:

  • iterable – 可迭代对象。
  • key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
  • reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

返回值: 返回重新排序的列表

2. sorted()函数按key值对字典进行排序

dict = {'apple':20, 'banana':14, 'peach':25, 'orange':16, 'tomato':10}
print(sorted(dict.keys()))

输出:

['apple', 'banana', 'orange', 'peach', 'tomato']

直接使用sorted(d.keys())就能按key值对字典排序,这里是按照键的首字母顺序对key值排序的,如果想按照倒序排序的话,则只要将reverse置为true即可。

3. sorted()函数按value值对字典进行排序

dict = {'apple':20, 'banana':14, 'peach':25, 'orange':16, 'tomato':10}
print(sorted(dict.items(), key = lambda item:item[1]))

输出:

[('tomato', 10), ('banana', 14), ('orange', 16), ('apple', 20), ('peach', 25)]
  • Python 字典的 items() 函数 以列表返回可遍历的(键, 值) 元组数组。所以此处的 dict.items() 实际上是将 dict 转换为可迭代对象,迭代对象的元素为 (‘apple’, 20), (‘banana’, 14), (‘peach’, 25), (‘orange’, 16), (‘tomato’, 10)
  • 这篇文章里有lambda表达式的详细介绍:https://www.cnblogs.com/jszfy/p/11148963.html

将lambda函数作为参数传递给sorted函数:
此时lambda函数用于指定对列表中所有元素进行排序的准则。
例如sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
将列表[1, 2, 3, 4, 5, 6, 7, 8, 9]按照元素与5距离从小到大进行排序,其结果是[5, 4, 6, 3, 7, 2, 8, 1, 9]。

而这里key参数对应的lambda表达式的意思则是选取元组中的第二个元素作为比较对象(若要选取第一个元素作为比较对象,可以写作key=lambda item:item[0],也就是键作为比较对象。采用这种方法可以对字典的value进行排序。

  • 注意: sorted()方法返回的是一个新的list,而不是在原来的基础上进行的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值