33算法与数据结构

算法与数据结构

程序 = 数据结构 + 算法。
一般而言,二者是职业生涯中的门槛,不了解它们,你会非常迅速地碰到职业的天花板。

什么是算法,什么是数据结构
算法实战:动手实现二分查找
算法实战:动手实现快速排序
数据结构实战:动手实现栈
数据结构实战:动手实现链表
ArrayList源码分析
HashMap源码分析

为什么我们需要算法和数据结构?

  • 计算机世界的基石,是程序员的内功
  • 对代码效率的提升是本质的R
  • 面试需要……

今天的所有算法和数据结构 都要求能够手写

基本数据结构

数组

  • 随机寻址
    • 常数时间
  • 插入/删除
    • 线性时间
  • 查找
    • 无序:线性时间
    • 有序:对数时间(二分查找)
  • 【要求】手写二分查找

链表

  • 寻址
  • 线性时间
  • 插入/删除
  • 常数时间
  • 查找
  • 线性时间
  • 【要求】手写
  • 翻转链表
  • 判断链表是否成环

栈 Stack

  • FILO (First In Last Out)
  • 应用:方法栈
  • 【要求】手写一个栈的实现

队列Queue

  • FIFO (First In First Out)
  • 应用:线程池
  • 【要求】手写一个队列的实现

哈希表

  • 查找/插入/删除操作都是0(1)
  • 哈希算法与碰撞
  • 哈希桶的内部实现

二叉树

  • 二叉树有两个孩子
  • 相应的,多叉树有多个孩子
  • 【要求】手写:
  • 二叉树的深度优先遍历
  • 二叉树的广度优先遍历

搜索二叉树

  • —棵经过精心设计的二叉树
  • 可以将搜索效率降低到对数时间
  • 致命缺点:可能会退化成链表
  • 红黑树

算法

算法的复杂度

  • 时间复杂度
    • O(1) - 哈希桶/数组随机寻址(常数)
    • O(n) - 遍历(线性)
    • O(log(n)) - 二分查找,二叉树(对数)
      • 使用条件:查找序列是顺序结构,有序
      • 优点 比较次数少,查找速度快,平均性能好
      • 缺点 要求待查表为有序表,且插入删除困难
    • O(n*log(n)) - 基于比较的排序算法的下界
    • O(n^2) - 冒泡排序(平方)
  • 时间复杂度的计算是忽略常数的
    • 即O(n)=O(2n)
  • 时间复杂度的计算中,高阶复杂度会吞并低阶复杂度
    • O(n^2)+O(n)=O(n^2)

排序算法-综述

  • 最基础的算法
  • 基于比较的排序算法的复杂度下界是O(nlog(n))
  • 排序的稳定性
  • Java默认用什么排序算法?

排序算法-冒泡排序

  • 最直观,最容易理解的排序算法
  • 想象一下你是体育委员,要对班级同学排序
  • 效率低,始终是0(^2)
  • 【要求】能手写

排序算法-快速排序

  • 每次将等待排序的数据划分成两部分
  • 递归进行
  • 直到所有数据有序

排序算法-归并排序

  • 分而治之
  • 将一个大问题分解成小问题
  • 解决小问题
  • 递归地解决大问题
  • 空间复杂度0(n)

拷问灵魂深处的问题

  • HashMap默认容量?

    • 16个桶
  • HashMap如何扩容?

    • 超过容量 * 负载因子
    • 扩容是之前的2倍
  • HashMap的数组大小为什么一定要是2的幂?

    • hash & (length - 1)
    • 只有长度是2的n次方的时候对它 -1 操作才能拿到二进制全是1的值,再进行按位与,用位运算快速拿到数组下标并且分布均匀
  • HashMap为什么是线程不安全的?

    • javadoc描述此实现不是同步的
    • HashMap底层是一个Entry数组,采用拉链法解决碰撞冲突
  • Java 7到8做了哪些改进?为什么?

  • Java 7的HashMap的问题

    • 非常容易碰到的死锁

    • 潜在的安全隐患

    • CVE-2011-4858 , Tomcat邮件组的讨论

    • Java 8的HashMap

    • 数组+链表/红黑树

    • 扩容时插入顺序的改进

    • 函数方法

      • forEach
      • compute系列
    • Map的新API

      • merge
      • replace

哈希表简介

  • 核心是基于哈希值的桶和链表
  • O(1)的平均查找、插入、删除时间
  • 致命缺陷是哈希值的碰撞(collision)
    举例子:

    • 电话本:A-Z把姓放到对应的字母
    • 哈希值:A-Z
    • 哈希桶:Z-张三-张三丰
    • 碰撞:张三-张三丰3
    • 桶的实现基于int hashCode
    • 哈希表:A-Z哈希桶

练习

基本算法练习

  • 二分查找

  • 排序算法

  • 二叉树的遍历

    • 深度优先和广度优先
    • 深度优先遍历,是指对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
    • 先序遍历:先访问根,在访问左子树,最后访问右子树,总结就是“根左右”;
    • 中序遍历:先访问左子树,再访问根,最后访问右子树,总结就是“左根右”;
    • 后序遍历:先访问左子树,再访问右子树,最后访问根,总结就是“左右根”。
    • 广度优先遍历,是指从上至下逐层访问,又称层次遍历。每一层从左至右访问,该层结束后进入下一层访问,直至没有节点为止。

    基本数据结构练习

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注