2叉树排序缺失元素查找
为什么80%的码农都做不了架构师?>>>
问题
- 在一组相同类型的数据中(对象、数组、字符串、整形等任意类型的数据结构)请用时间空间最优的方式查找缺失的一项。例如有一组数据["A","B","C","D","E","F","G"],现在给到["B","D","A","F"."G"],需要找到缺失数据"C"?数据的个数不定。
- 扩展上面的问题,用最优的方式查找缺失的多项。
解决
2层循环逐个比对查找
最简单的办法当然是逐项比对,几乎所有语言都提供对象实例、字符串、数字的比对方法。
但是这样做有2个问题:
- 少量数据可行,但是海量数据肯定会非常慢,因为时间复杂度是O(n^2)。而且第一层循环是全遍历,第二层循要遍历n/2。
- 在比对过程中如果是字符串比对,效率会非常差。
编码2叉树查找
可以对所有的事物进行有序编码,然后通过编码索引到对应的元素。编码也没有什么特别的要求,只要每增加一项将编码加一即可。例如上面的例子["A","B","C","D","E","F","G"],对其编码建立索引:
{1:"A",2:"B",3:"C",4:"D",5:"E",6:"F",7:"G"}
这是一个标准的dict结构(Java中的map结构)。任何时候增加新的项目只要编码加一即可:
{1:"A",2:"B",3:"C",4:"D",5:"E",6:"F",7:"G",8:"ADD ITEM"}
使用编码还有一个好处是还可以查找一组不同类型的数据。
建立编码之后实际上就转换为一个数字查询问题。
如果仅仅是查找一个缺失项,实际上有一个非常简便的算法——求和计算差值:
# origin_numbers是所有编码的列表,例如[1,2,3,4,5,6,7,8,9,10]。# random_numbers是缺失了一项的编码无序表,例如[6,2,5,4,7,8,9,10,1]。for _num in origin_numbers:total_sum = total_sum + _numfor _num in random_numbers:without_sum = without_sum + _num
差值正好是缺失的项目索引值。
但是如果是查找多个缺失项,只能用2叉树:
import copy
import random as rand
import datetime
import time# 2叉树结构
class Link:def __init__(self, value):self.value = valueself.left = Noneself.right = Nonedef insert(self, value):if value < self.value:self.__addLeftLeaf__(value)else:self.__addRightLeaf__(value)def __addLeftLeaf__(self, value):if self.left is not None:self.left.insert(value)else:self.left = Link(value)def __addRightLeaf__(self, value):if self.right is not None:self.right.insert(value)else:self.right = Link(value)def traversal(self, _list, _without):if self.left is not None:self.left.traversal(_list, _without)length = len(_list)if 0 < length:tail = _list[length - 1]diff = self.value - (tail + 1)if 0 < diff:for _d in range(1, diff + 1):_without.append(self.value - _d)_list.append(self.value)if self.right is not None:self.right.traversal(_list, _without)# 从队列中移除项目
def remove_number(without_size, numbers):for count in range(without_size):del numbers[rand.randrange(len(numbers))]return numbers# 使用有序数组生成随机数组
def generation_random(without_size, origin_numbers):origin_numbers_options = copy.copy(origin_numbers)length = len(origin_numbers)random_numbers = []# 随机while 0 < length:rand_number = rand.randrange(length)random_numbers.append(origin_numbers_options[rand_number])del origin_numbers_options[rand_number]length = len(origin_numbers_options)return remove_number(without_size, random_numbers)#
def generation_origin_numbers(without_size=1, total=10000):origin_numbers = list(range(total))return origin_numbers, generation_random(without_size, origin_numbers)def tree_2_leaf(numbers):root = Link(numbers[0])for pos in range(1, len(numbers)):root.insert(numbers[pos])# 使用二叉树_list = []_without = []root.traversal(_list=_list, _without=_without)return _withoutdef without_one_number(origin_numbers, random_numbers):print("=============== without_one_number start ==================")sum_search_start = time.time()total_sum = 0without_sum = 0print("Sum Search Begin.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))for _num in origin_numbers:total_sum = total_sum + _numfor _num in random_numbers:without_sum = without_sum + _numtree_search_start = sum_search_end = time.time()print("Sum Search Complete.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))print("Timer:{} S".format(sum_search_end - sum_search_start))print("Total Sum:{}".format(total_sum))print("Without One Number Sum:{}".format(without_sum))print("Without Number:{}".format(total_sum - without_sum))print("---")print("2 Tree Search Begin.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))without_number = tree_2_leaf(random_numbers)print("2 Tree Complete.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))print("Timer:{} S".format(time.time() - tree_search_start))print("Without Element:{}".format(without_number))print("=============== without_one_number end ==================")def without_multi_number(random_numbers):print("=============== without_multi_number start ==================")start = time.time()print("Search Begin.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))without_number = tree_2_leaf(random_numbers)print("Search End.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))print("Timer:{} S".format(time.time() - start))print("Without Element:{}".format(without_number))print("=============== without_multi_number end ==================")if __name__ == '__main__':print("Generation Numbers Begin.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))generation_number_start = time.time()origin, random = generation_origin_numbers()print("Generation Numbers Complete.({})".format(datetime.datetime.now().strftime('%H:%M:%S')))generation_number_end = time.time()print("Timer:{} S".format(generation_number_end - generation_number_start))without_one_number(origin, random)without_multi_number(remove_number(4, random))
转载于:https://my.oschina.net/chkui/blog/3009291
2叉树排序缺失元素查找相关推荐
- 算法----- 在排序数组中查找元素的第一个和最后一个位置
题目: 在排序数组中查找元素的第一个和最后一个位置给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置.你的算法时间复杂度必须是 O(log ...
- python 在排序数组中查找元素的第一个和最后一个位置
在排序数组中查找元素的第一个和最后一个位置 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置.如果数组中不存在目标值 target,返回 ...
- LeetCode (二分小专题)33搜索旋转排序数组34在排序数组中查找元素的第一个和最后一个位置35搜索插入位置
前言 国庆前最后一次打卡,国庆后继续开启,公众号bigsai回复进群欢迎加入打卡,如有帮助记得点赞收藏. 近期打卡记录: LeetCode 32最长有效括号(困难) (本周) LeetCode 30串 ...
- 6、leetcode34 在排序数组中查找元素的第一个位置和最后一个位置**
leetcode34 在排序数组中查找元素的第一个位置和最后一个位置 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 如果数组中不存 ...
- leetcode(34)在排序数组中查找元素的第一个和最后一个位置
在排序数组中查找元素的第一个和最后一个位置 class Solution {public int[] searchRange(int[] nums, int target) {int len = nu ...
- 34. 在排序数组中查找元素的第一个和最后一个位置 golang
34. 在排序数组中查找元素的第一个和最后一个位置 https://leetcode-cn.com/problems/find-first-and-last-position-of-element-i ...
- 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...
作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...
- LeetCode--34.在排序数组中查找元素第一个和最后一个位置(二分法)
在排序数组中查找元素第一个和最后一个位置(C++) 1. 题目描述 2. 题目分析 3. C++语言实现 1. 题目描述 难度:中等 2. 题目分析 看到题目我们需要知道以下几点: 数组是有序的 数组 ...
- 20200221:在排序数组中查找元素的第一个和最后一个位置(leetcode34)
在排序数组中查找元素的第一个和最后一个位置 题目 思路与算法 代码实现 题目 思路与算法 题目要求了算法复杂度为O(logN),因此必须是二分查找来实现,但是其实最简单的思路应该就是顺序和逆序的遍历了 ...
最新文章
- 人工智能入门:keras的example文件解析
- js生日计算年龄_如何提取身份证生日和年龄,几行VBA代码教你学会
- MySql笔记之数据表
- Python 中re.split()方法
- oracle错误号大全(查询ora错误号以及解决方法技巧)
- adb android源码分析,Android源码分析(十六)----adb shell 命令进行OTA升级
- rsyslod服务配置
- 曲线聚类_R语言确定聚类的最佳簇数:3种聚类优化方法
- 美国生活社交礼仪必读
- 怎么更好掌握Web前端技术?JS的跨域是怎么回事?
- android peopleactivity.java,Android面试基础篇---Activity(上)
- 听说,Java程序员都是吃青春饭的?
- 电源输出的Overshoot和Undershoot 测试
- 维小帮景区导航系统:不止是导航,更是营销获客的流量密码
- netty 服务端主动向客户端发信息
- 依概率收敛和依分布收敛(附一道例题)
- 郑州机电工程学校计算机部,郑州机电工程学校
- 解决因IPV6造成的网易云音乐一直缓冲的问题
- android 自动唤醒解锁,Android-唤醒并解锁Devi
- ThinkPHP5之Ajax分页
热门文章
- 小程序 cover-view 字体_【企商云】2021年,要知道的9个小程序开发流程清单
- C++之访问命名空间/名字空间元素的三种方式
- java棋盘覆盖分治法_【单选题】实现棋盘覆盖算法利用的算法是( )
A. 分治法 B. 动态规划法 C. 贪心法 D. 回溯法...
- 集合拆成固定长度的小集合_《集合啦动物森友会》钓鱼怎么玩?钓鱼小技巧攻略分享...
- python 递归的最大层数_练习题-Python的最大递归层数
- qfile如何清空内容_数据丢失的场景有哪些?如何找回丢失的数据?
- 苹果手机html查看器在哪,web前端案例-苹果手机图片查看器
- python网页请求超时_python爬虫多次请求超时的几种重试方法(6种)
- java 怎么用毫秒_java1.8中如何使用精确到毫秒的时间
- oracle12c asm 冗余,深入分析:12C ASM Normal冗余中PDB文件块号与AU关系与恢复