Python算法概述(2)_(key+1)%2什么意思(1),字节跳动Python三面凉凉

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Python全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Python知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注Python)
img

正文

⑦ 若key > keyMid且low != Mid +1,则令low=Mid+1

4.2 常见的哈希法简介

哈希法是使用哈希函数来计算一个键值所对应的地址,进而建立哈希表格,然后依靠哈希函数来查找到各个键值存放在表格中的地址,查找速度与数据多少无关,在没有碰撞和溢出的情况下,一次读取即可完成。哈希还具有保密性高的特点,因为不事先知道哈希函数就无法查找到数据,信息技术上有许多哈希法的应用,特别在数据压缩和加解密方面。
选择哈希函数时,不宜过于复杂,设计原则上至少符合计算机速度快和碰撞频率尽量低的两个特点。
常见的哈希算法有除留余数法、取平方法、折叠法及数字分析法。

4.2.1 除留余数法

最简单的哈希函数是将数据除以某一个常数之后,取余数来当索引。
例如,在一个13个位置的数组中,只使用7个地址,值分别是12、65、70、99、33、67、48。我们可以把数组内的值除以13,并以其余数来当作数组的下标(作为索引),以下表示:
H(key) = key mod B
在这里插入图片描述

4.2.2 平方取中法

取平方法和除留取余法相当类似,就是先计算数据的平方,之后再取中间的某段数字作为索引。
下例中,用平方取中法,并将数据存放在100个地址空间中,操作步骤如下:
① 将12、65、70、99、33、67、51平方如下:
144、4225、4900、9801、1089、4489、2601
② 再取百位和十位数作为键值,分别为:
14、22、90、80、08、48、60
7个数字存在100个地址空间的索引键值如下:

F(14)=12
F(22)=65
F(90)=70
F(80)=99
F(8)=33
F(48)=67
F(60)=51

若实际空间介于09(10个空间),但取百分数和十位数的值介于099(共一百个空间),则必须将平方取中法第一次所求得的键值再压缩1/10才可以将100个可能产生的值对应到10个空间,即将每一个键值除以10取整(下面采用DIV运算符作为取整数的除法),可以得到下列对应关系:
在这里插入图片描述

4.2.3 折叠法

折叠法是将数据转成一串数字后,先将这串数字拆分成几个部分,再把他们加起来就得到这个键值的Bucket Address(桶地址)。
例如有一个数字,转换成数字后为:2365479125443
若以每4个数字为一个部分,则可拆分为2365、4791、2544、3。
将这4组数字加起来之后即为索引值:
移动折叠法:

  2365
  4691
  2544
+    3
————————
  9073 ——>bucket address(桶地址)

哈希法的设计原则之一就是降低碰撞,如果希望降低碰撞的机会,就可将上述每一部分的奇数或偶数反转,再相加来取得其bucket address,这种改进式的做法称为“边界折叠法(folding at the boundaries)”
(1)情况一:将偶数反转

  2365  (奇数,不转)
  4691  (奇数,不转)
  4452  (偶数,反转)
+    3   奇数,不转)
————————
 11611  —>  bucket address(桶地址)

(1)情况二:将奇数反转

  2365  (奇数,反转)
  4691  (奇数,反转)
  2544  (偶数,不转)
+    3  (奇数,反转)
————————
 10153  —>  bucket address(桶地址)

4.2.4 数字分析法

数字分析法适用于数据不会更改,且为数字类型的静态表。在决定哈希函数时先逐一检查数据的相对位置和分布情况,将重复性高的部分删除。

4.3 碰撞与溢出问题的处理

在哈希法中,当标识符要放在某个桶(Bucket,哈希表中存储数据的位置)时,若桶已经满了,就会发生溢出(Overflow);另一方面哈希的理想情况是所有数据经过哈希函数运算后都得到不同的值,但现实情况是即使所有关键字段的值都不相同,还是可能得到相同的地址,于是就发生了碰撞(Collision)问题。因此,碰撞发生后处理溢出的问题就显得相当重要。常见的算法有以下几种:

4.3.1 线性探测法

线性探测是当发生碰撞的情况时,若该索引对应的存储位置已有数据,则以线性的方法往后寻找空的存储位置,一旦找到位置就把数据放进去。线性探测法通常把哈希的位置视为环形结构,如此一来若后面的位置已被填满而前面还有位置时,可以将数据存放在前面。

4.3.2 平方探测法

平方探测法中,当溢出发生时,下一次查找的地址是(f(x)+i^2)mod B 与 f(f(x)-i^2) mod B,即让数据值加或减i的平方,例如数据值key,哈希函数f:

 第一次查找: f(key)
 第二次查找:f((key)+1^2)%B
 第三次查找:f((key)-1^2)%B
 第四次查找:f((key)+2^2)%B
 第五次查找:f((key)-2^2)%B
 ......
 ......
 ......

第n次查找:(f(key)+((B-1)/2)^2)%B,其中,B必须为4j+3型的质数,且1<=i<=(B-1)/2

4.3.3 再哈希法

再哈希就是一开始就先设置一系列的哈希函数,如果使用第一种哈希函数出现溢出时就改用第二种,如果第二种也出现溢出则改用第三种,一直到没有发生溢出为止。
例如,h1为key%11,h2为keykey,h3为keykey%11,h4…。接着请使用再哈希处理下列数据碰撞的问题:
681,467,633,511,100,164,472,438,445,366,118:
其中哈希函数为(此处的 m=13)

 F1=h(key)=key MOD m
 F2=h(key)=(key+2) MOD m
 F3=h(key)=(key+4) MOD m

说明如下:
(1) 使用第一种哈希函数h(key)=key MOD 13,所得的哈希地址如下:

 618 -> 5
 467 -> 12
 633 -> 9
 511 -> 4
 100 -> 9
 164 -> 8
 472 -> 4
 438 -> 9
 445 -> 3
 366 -> 2
 118 -> 1

(2) 其中100,472,438都发生碰撞,再使用第二种哈希函数h(value+2)=(value+2) MOD 13,进行数据的地址安排:

100 ->h(100+2)=102 mod 13 =11
472 ->h(472+2)=474 mod 13=6
438 ->h(438+2)=440 mod 13=11

(3) 438仍发生碰撞问题,故接着使用第三种哈希函数h(value+4)=(438+4) MOD 13,重新进行438地址的安排:
438 ->h(438+4)=442 mod 13=11
经过三次再哈希后,数据的地址安排如下:
在这里插入图片描述

五、数组与链表算法

1、静态数据结构(stattic data struct)
数组类型是典型的静态数据结构,它使用连续分配的内存空间,来存储有序表中的数据。静态数据结构是在编译时就给相关额变量分配好的内存空间,由于建立静态数据结构的初期必须事先声明最大可能要占用的固定内存空间,因此容易造成内存浪费。
例如,数据类型就是一种典型的静态数据结构。优点是设计时相当简单,而且读取与修改表中任意一个元素的时间是固定的。缺点是删除或加入数据时,需要移动大量的数据。

2、动态数据结构(dynamic data struct)
动态数据结构又称为“链表”,它使用不连续的内存空间存储具有线性表特性的数据。优点是数据的插入或删除都相当方便,不需移动大量的数据。内存分配是在程序执行时才进行的,所以不需事先声明,这能充分节省内存。优点是在设计数据结构时较麻烦,查找数据时需要按顺序查找,不像数组那样可随机读取。

5.1矩阵

数学角度看,对于m × n矩阵(matrix)的形式,可用计算机中A(m,n)的二位数组来描述。
大部分矩阵的运算和应用都可以使用计算机中的二维数组解决。
在这里插入图片描述
朋友们可以去温习下线性代数
5.1.1 矩阵相加算法
5.1.2 矩阵相乘算法
5.1.3 转置矩阵

5.2 建立单向链表

若以动态分配产生链表节点的节点,可先定义一个类,接着在该类中定义一个指针字段,作用是指向下一个链表节点,该类中至少要有一个数据字段。
例如,声明一个公司员工成绩链表节点的结构声明,包含姓名(name),工资(salary)两个数据字段与一个指针字段(next)。
可以声明如下:

class employee:
    def \_\_init\_\_(self):
        self.name=''
        self.salary=0
        self.next=None

完成声明后,可动态建立链表中的每个节点。假设现要新增一个节点至链表的末尾,且ptr指向链表的每一个节点,在程序上必须设计4个步骤:

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注python)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注python)
[外链图片转存中…(img-vWNcKHFj-1713376980988)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值