算法&数据结构心得

  • 对比链表和数组,数组的查找速度比链表快,这是为什么呢?结合计算机组成原理的知识,我的推测是:用index查找数组中的项目时,CPU首先读取数组的地址到寄存器,再加上index乘以系数可直接得到项目的地址,只需要读一次内存;而查找链表中的项目时index有多大,就要读内存多少次。
  • 哈希表的大小往往是质数,因为哈希函数返回值都需要除以哈希表的size求余数,如果size不是质数的话返回值很容易重合
  • 检验一个整数是否质数:试除所有不大于自身的平方根的质数
  • 求一定范围内的质数可以用筛除法
  • 尾递归可优化递归,使之不易爆栈,它是这种形式let re = (n,r) => re(n-1, r* n); re(6,1),也就是上一轮的计算结果作为参数直接传参给下一轮。形成return -> return -> return的行为,语法含义很像一个for循环。
  • 树形结构有一个很重要的优点就是抽象能力,比如二叉搜索树:可以把curNode的left节点上所有的枝叶抽象成"一堆比curNode小的Node",也可以把某节点左侧(上游+下游)节点全部抽象为比该节点小的Node.
  • 现有无序的let arr: number[],要把它重构为二叉树,做法是:先排序,拿到arr[Math.floor(arr.length/2)]作为根节点,比它小的放left,大的放right,递归之。
  • 平衡二叉树可以抽象为以下步骤:1 旋转外围节点来切换根节点 2 出现子三叉树,转化为二叉树; 无论如何旋转外层节点(切换根节点),原根节点都不会出现三叉,而其他节点很可能出现三叉
  • 插入排序一般有两层循环:外循环(i)从左往右遍历数组,内层循环以i-1为起点从右往左遍历数组,在找到插入的位置之前,每次内层循环都把当前component向右复制一位,找到位置则插入,结束本次外层循环。
  • 分治法的原理:把n规模的问题分解成多个(几个?)更小规模(多小?)的问题,一直到规模足够小,得出每个分支的结果,再合并。
  • O(g(n)) is a Set of function like {f(n) | exist constant [c,m] that f(n) $lt or equal cg(n) for all number $gt m}
  • omega 与 O相反,theta 是 O 和 omega 的交集
  • 小o和omega相当于大O和Omega集合定义中把equal去掉,m由exist变为for all
  • 快速排序的原理与二叉查找树相同,如果输入是已排序的,unlucky,所以引入随机pivot。
  • 算法运行时间对应于决策树路径的深度,决策树的叶节点数量为n!,指数级。基于比较的排序至少O(nlgn)的原因是,对应的决策树高度至少是O(nlgn)
  • counting sort 先确定排序数组中元素的范围,比如1-k,声明一个length为k的数组,存储1-k中每个数字出现的次数,以此为基础,遍历arr,并对1-k数组进行对应的操作。复杂度为O(k+n),因此在k很小的时候它是非常高效的。
  • 好的排序算法应具有稳定性: 排序过程中已经有序的部分不会又变得无序再排序。这显然是浪费。
  • radix sort:设一个int有b个digits,r是digits步长,也就是说在2r进制下有b/r位,然后从低位开始遍历每位,用该位的数字进行countingSort,时间复杂度为O(b/r(n+2r))。关于r的选取,应保证n>=2r
  • B-树:为了减少硬盘IO次数将二叉树层数压缩: 1 一个节点内有多个元素 2 一个节点有较多children; 在改动时应该会遵循这样的原则: 1 自平衡 2 尽量制造少元素的节点(方便之后的元素直接插入节点)
  • 问题:如何判断链表有环,如果有环,找出入环节点——两个指针同时从起点起步,一个slow一个fast,每轮循环slow走一步,fast走两步(为何是两步?设计,使得s=nr,不变的是相遇时fast走了2s,slow走了s),如果有环,入环后它们一定会相遇,因为它们的相对速度是一步。接下来找出入环节点:设相遇时slow走了s步,fast走了2s步,并在环内已经跑了n圈,环长r步,则有2s = s + nr,得出s = nr(关键!设计2倍速导致),fast比slow多走了整n圈,这时slow走的步数是nr,设起点到入环节点的步数为a, slow再走a 步会到达入环节点,即nr + a, 于是 nr + a = a + nr, 这里的a + nr是先入环再走n圈的步数, 所以把另一节点从起点出发与slow同时启动,步长为1,相遇时就是入环节点
  • 关于动态规划,有一个我认为的要点,那就是决策树逆转,顺着时间可以生成决策树,逆着来也可以。
  • 递归和动态规划的数学基础是数学归纳法
  • 双指针使用场景:链表、排序过的数组和链表
  • 可以考虑先写出暴力法,再优化
  • while 循环的条件范围要尽量的小,能用> <就不用 !==,避免死循环
  • 回溯算法:针对的问题(例如全排列)一般有这样的特征:树形遍历到末端得出一部分答案,上层到下层一般会传递参数,如果这些参数是引用类型或有一定的结构,可能会造成很大的空间复杂度(也间接加大了时间复杂度),此时引入回溯的概念,上层到下层的一部分传参被提升到全局,如同stack-栈,进入下层时参数被修改,return到上层时又撤回修改,因此代码在此处往往出现对称性,建议画出树形图,从深度广度两方面分析
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值