二叉树_存在重复元素/是否为平滑二叉树

Posted NLPer项目算法实战

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树_存在重复元素/是否为平滑二叉树相关的知识,希望对你有一定的参考价值。

"""存在重复元素 III给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。如果存在则返回 true,不存在返回 false。示例 1:输入:nums = [1,2,3,1], k = 3, t = 0输出:true示例 2:输入:nums = [1,0,1,1], k = 1, t = 2输出:true示例 3:输入:nums = [1,5,9,1,5,9], k = 2, t = 3输出:false提示:0 <= nums.length <= 2 * 104-231 <= nums[i] <= 231 - 10 <= k <= 1040 <= t <= 231 - 1相关标签"""
# 方法1暴力求解法class Solution: def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool: for i in range(len(nums)): for j in range(i + 1,len(nums)): if abs(nums[i] - nums[j]) <= t and abs(i - j) <= k: return True return False

"""解题思路,利用桶,O(N)时间复杂度遍历一遍数组for i in range(len(nums))对于任意的数nums[i] 利用 nums[i]//(t+1) 就可以把数分到不同的桶中,这些桶的数字分别是 0到t (0号桶) t+1到2t(1号桶) ... nt+1到(n+1)t为啥这样整呢?桶内元素绝对满足 abs(nums[i] - nums[j]) <= t相邻的桶有可能出现 abs(nums[i] - nums[j]) <= t不相邻的桶一定不会出现 abs(nums[i] - nums[j]) <= t , 你可以想一下0号桶和2号桶,他们最大值和最小值差了t+1这就是为啥//t+1的原因好,还有个条件:abs(i - j) <= k思考一下:在i越过k之前,需要考虑这个条件吗?不需要,因为总共长度最多k+1,再怎么减也是小于等于k的。所以在越过k之前,我们根据nums[i]//(t+1)依次把nums[i]往总桶里加。这里可以使用哈希表来存桶号:桶值,如果出现:要加入的这个桶值存在,说明之前有某个j,使得nums[j]//(t+1)==nums[i]//(t+1),根据上面第一条那就返回True(所以根据这条,这些桶最多只有一个数,如果有俩早就返回True了)。如果不存在,加入哈希表 (key:value)为 (桶值:nums[i]) , 然后跟相邻的桶的value比较一下,如果满足abs(nums[i] - nums[j]) <= t ,返回True。i越过k了呢?很简单,那么对于nums[i-k],他已经不在我们考虑范围了,所以把这个数带来的操作销毁掉,也就是把桶nums[i]//(t+1)删除掉即可"""
# 方法2分桶class Solution: def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool: all_buckets = {} bucket_size = t + 1 for i in range(len(nums)): bucket_num = nums[i] // bucket_size if bucket_num in all_buckets: return True all_buckets[bucket_num] = nums[i] if (bucket_num - 1) in all_buckets and abs(all_buckets[bucket_num - 1] - nums[i]) <= t: return True if (bucket_num + 1) in all_buckets and abs(all_buckets[bucket_num + 1] - nums[i]) <= t: return True if i >= k: all_buckets.pop(nums[i - k] // bucket_size) return False

# 解题思路,利用桶,O(N)时间复杂度
# 二叉搜索树from sortedcontainers import SortedSetclass Solution: def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool: sorted_set = SortedSet() for i in range(len(nums)): num = nums[i] # find the successor of current element if sorted_set and sorted_set.bisect_left(num) < len(sorted_set): if sorted_set[sorted_set.bisect_left(num)] <= num + t: return True # find the predecessor of current element if sorted_set and sorted_set.bisect_left(num) != 0: if num <= sorted_set[sorted_set.bisect_left(num) - 1] + t: return True sorted_set.add(num) if len(sorted_set) > k: sorted_set.remove(nums[i - k]) return False








"""给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1 。
示例 1:输入:root = [3,9,20,null,null,15,7]输出:true示例 2:输入:root = [1,2,2,3,3,null,null,4,4]输出:false示例 3:输入:root = []输出:true
树结构中的常见用语:节点的深度 - 从树的根节点到该节点的边数节点的高度 - 该节点和叶子之间最长路径上的边数树的高度 - 其根节点的高度
一个高度平衡的二叉搜索树(平衡二叉搜索树)是在插入和删除任何节点之后,可以自动保持其高度最小。也就是说,有 N 个节点的平衡二叉搜索树,它的高度是 logN 。并且,每个节点的两个子树的高度不会相差超过 1。为什么是 logN 呢?一个高度为 h 的二叉树换言之,一个有 N 个节点,且高度为 h 的二叉树所以:我们已经介绍过了二叉树及其相关操作, 包括搜索、插入、删除。当分析这些操作的时间复杂度时,我们需要注意的是树的高度是十分重要的考量因素。以搜索操作为例,如果二叉搜索树的高度为 h ,则时间复杂度为 O(h) 。二叉搜索树的高度的确很重要。所以,我们来讨论一下树的节点总数 N 和高度 h 之间的关系。对于一个平衡二叉搜索树, 我们已经在前文中提过,但一个普通的二叉搜索树,在最坏的情况下,它可以退化成一个链。因此,具有 N 个节点的二叉搜索树的高度在 logN 到 N 区间变化。也就是说,搜索操作的时间复杂度可以从 logN 变化到 N 。这是一个巨大的性能差异。所以说,高度平衡的二叉搜索树对提高性能起着重要作"""# 方法1自底至顶class Solution: def isBalanced(self, root: TreeNode) -> bool: return self.recur(root) != -1
def recur(self, root): if not root: return 0 left = self.recur(root.left)# 相当于子树一路到底 if left == -1: return -1 right = self.recur(root.right)# 相当于子树一路到底 if right == -1: return -1 return max(right, left) + 1 if abs(left - right) < 2 else -1 # 相当于子树一路到底 往回撤的时候再判断,一旦不满足提前终止"""复杂度分析:时间复杂度 O(N): N 为树的节点数;最差情况下,需要递归遍历树的所有节点。空间复杂度 O(N): 最差情况下(树退化为链表时),系统递归需要使用 O(N)的栈空间。"""
# 方法2自顶至底class Solution: def isBalanced(self, root: TreeNode) -> bool: if not root: return True return abs(self.depth(root.left) - self.depth(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
def depth(self, root): if not root: return 0 return max(self.depth(root.left), self.depth(root.right)) + 1
"""复杂度分析:时间复杂度O(Nlog2N): 最差情况下, isBalanced(root) 遍历树所有节点,占用 O(N) ;判断每个节点的最大高度 depth(root) 需要遍历 各子树的所有节点 ,子树的节点数的复杂度为 O(log2N) 。空间复杂度 O(N): 最差情况下(树退化为链表时),系统递归需要使用 O(N) 的栈空间。"""


以上是关于二叉树_存在重复元素/是否为平滑二叉树的主要内容,如果未能解决你的问题,请参考以下文章

二叉树遍历练习题

N39_判断该二叉树是否是平衡二叉树。

几道和「二叉树」有关的算法面试题

二叉树是否存在节点和为指定值的路径/路径总和Ⅱ

python代码判断两棵二叉树是否相同

二叉树的镜像(反转二叉树)