zoukankan      html  css  js  c++  java
  • 算法

    1. 怎么学习算法? 

        1)复杂度分析方法

        2)要学习它的“来历”“自身的特点”“适合解决的问题”以及“实际的应用场景"

    2. 做算法题注意事项:

        1) 临界条件

        2)时间复杂度,空间分复杂度

        3)终止条件

    算法学习:

    1. 边学边练,适度刷题

    2. 多问,多思考,多互动

    3. 打怪升级学习方法

    4. 知识需要沉淀,不要试图一下子学会所有

    时间复杂度分析:

    1. 只关注循环执行最多的一段代码

    2. 加法法则:总复杂度等于量级最大的那段代码的复杂度

    3. 乘法原则:嵌套代码的复杂度等于嵌套内外代码的复杂度乘积

    4. 多项式量级,非多项式量级(O(2n次方) 和 O(n!))

    空间复杂度分析

    浅析最好、最坏、平均、均摊时间复杂度

    数组:如何实现随机访问?

    1)线性表

    2)第二个是连续的内存空间和相同类型的数据

    容器能否完全替代数组?

    不能,例如:动态扩容会浪费空间。

    低效的插入和删除操作

    链表和数组对比:

    链表的空间不一定连续,而数组空间必须连续。

    数组和链表的对比,并不能局限于时间复杂度。而且,在实际的软件,不能仅仅利用复杂度分析就决定使用哪个数据结构来存储数据。

    数组简单易用,在实现上使用的是连续的内存空间,可以借助 CPU 的缓存机制,预读数组中的数据,所以访问效率更高。而链表在内存中并不是连续存储,所以对 CPU 缓存不友好,没办法有效预读。

    数组的缺点是大小固定,一经声明就要占用整块连续内存空间。如果声明的数组过大,系统可能没有足够的连续内存空间分配给它,导致“内存不足(out of memory)”。如果声明的数组过小,则可能出现不够用的情况。

    这时只能再申请一个更大的内存空间,把原数组拷贝进去,非常费时。链表本身没有大小的限制,天然地支持动态扩容,我觉得这也是它与数组最大的区别。

    双向链表和单向链表比较:

    除了插入、删除操作有优势之外,对于一个有序链表,双向链表的按值查询的效率也要比单链表高一些。因为,我们可以记录上次查找的位置 p,每次查询时,根据要查找的值与 p 的大小关系,决定是往前还是往后查找,所以平均只需要查找一半的数据。

    现在,你有没有觉得双向链表要比单链表更加高效呢?这就是为什么在实际的软件开发中,双向链表尽管比较费内存,但还是比单链表的应用更加广泛的原因。如果你熟悉 Java 语言,你肯定用过 LinkedHashMap 这个容器。如果你深入研究 LinkedHashMap 的实现原理,就会发现其中就用到了双向链表这种数据结构。

    用空间换时间:当内存空间充足的时候,如果我们更加追求代码的执行速度,我们就可以选择空间复杂度相对较高、但时间复杂度相对很低的算法或者数据结构。相反,如果内存比较紧缺,比如代码跑在手机或者单片机上,这个时候,就要反过来用时间换空间的设计思路。

    如何正确写出正确的链表代码?

    1. 理解指针或引用的含义。

    2. 警惕指针丢失和内存泄露

    3. 利用哨兵和简化实现难度

    4. 重点留意边界条件处理

    5. 举例画图,辅助思考

    6. 多写多练没有捷径

    栈:

    1. 用数组实现的栈,我们叫作顺序栈,用链表实现的栈,我们叫作链式栈。

    队列:

    顺序队列和链式队列

    循环队列(队列满的条件:(tail+1)%n=head)、并发队列、阻塞队列(锁、CAS)

    递归的三个条件:

    1. 一个问题可以分解成几个子问题

    2. 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一致。

    3. 存在递归终止条件

    注意:

    1. 递归代码要警惕堆栈溢出

    2. 递归代码要警惕重复计算

    3. 将递归代码改成非递归代码

    二分法:

    1. 二分查找,尽量用while循环来做,避免栈溢出。考虑使用 low<=high,而不是 low<high。

    2. mid=(low+high)/2 这种写法是有问题的。因为如果 low 和 high 比较大的话,两者之和就有可能会溢出。改进的方法是将 mid 的计算方式写成 low+(high-low)/2。

        更进一步,如果要将性能优化到极致的话,我们可以将这里的除以 2 操作转化成位运算 low+((high-low)>>1)。因为相比除法运算来说,计算机处理位运算要快得多。

    3. 注意边界条件,比最小值还小,比最大值更大的特殊情况。

    4. mid值判断不符合条件,赋值的时候,可以使用 low = mid + 1 或者 high = mid - 1 。这个需要注意具体使用场景是否可用。

    5. low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,就可能会发生死循环。比如,当 high=3,low=3 时,如果 a[3] 不等于 value,就会导致一直循环不退出。

    小的知识点:

    1. 整数相乘或者相加,如果超过最大整数值,会变成负数

  • 相关阅读:
    破解Mac版MyEclipse-2017-ci3
    JAVA8 十大新特性详解
    Java 1.8 时间日期库的20个使用示例
    20180206 反射中模块化开发的上课思路
    反射在数据库读写中的应用
    浅谈多线程并发
    Mac OS Git 安装
    MAC node + git + bower 简单安装
    Mac OS 下 eclipse中文乱码解决方法(eclipse for mac 中文乱码)
    【精华】MacOS 10.13.2 环境下安装eclipse
  • 原文地址:https://www.cnblogs.com/Jtianlin/p/10794629.html
Copyright © 2011-2022 走看看