《算法图解》学习日记

学习目标:

学习《算法图解》这本书,记录学习到的内容

学习内容:

这本书将算法像小说一样解释,简单易懂。主要涉及算法有:

  1. 二分查找
  2. 选择排序
  3. 快速排序
  4. 广度优先搜索
  5. 狄克斯特拉算法
  6. 贪婪算法
  7. 动态规划
  8. K最近邻算法

章节总结

第一章:算法介绍

  • 该章主要介绍了二分查找大O表示法。算法对性能的影响
  • 程序 = 算法 + 数据结构

二分查找算法

  • 需要有序数组
  • 时间:O(log(n)) 此处log = log2()
  • 空间:O(1)
public int binary_serach(List<int> list, int item) {
	int low = 0;
	int high = item.Count - 1;
	while (low <= high) {
		int mid = (high + low) / 2;
		int guess = list[mid];

		if (guess == item) {
			return mid; // 找到了
		}
		
		if (guess > item) {
			high = mid - 1;	
		} else {
			low = mid + 1;
		}
	}

	return -1; // 没有找到目标
}

第二章:选择排序

  • 介绍了链表、数组、选择排序
  • 数组读取速度很快,插入删除很慢
  • 链表插入删除很快,读取速度比数组慢

选择排序

  • 时间:O(n^2)
  • 空间:O(n)
public int selectionSort(List<int> list) {
	List<int> newList = new();
	for (int i = 0; i < list.Count; i++) {
		int idx = findSmallest(list);
		newList.add(list[idx]);
		list.remove(idx);
	}

	return newList;
}
private int findSmallest(List<int> list) {
	int smallestIdx = 0;
	for (int i = 1; i < list.Count; i++) {
		if (list[smallestIdx] < list[i]) {
			smallestIdx = i;
		}
	}

	return smallestIdx;
}

第三章:递归

  • 讲了递归和栈,可以用栈的方式存储递归的数据,达到用单纯的循环来实现递归方法
  • 计算机在内部使用被称为调用栈的栈
  • 每个递归函数都有两个条件:基线条件和递归条件

第四章:快速排序

  • 分而治之(divide and conquer, D&C) 一种递归式问题解决方式
  • 分而治之并非可解决问题的算法,而是一种解决问题的思路
  • 两个步骤:
    1. 找到基线条件,该条件需尽可能简单
    2. 缩小规模,直至满足基线条件
  • 时间:O(nlog(n))
  • 空间:O(log(n))
void QuickSort(int[] arr, int left, int right) {
    int pivot = arr[(left + right) / 2];
    int i = left, j = right;
    while (i <= j) {
        // 分区操作
        while (arr[i] < pivot) i++;
        while (arr[j] > pivot) j--;
        if (i <= j) {
            // 交换元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
    }
    // 递归排序
    if (left < j) QuickSort(arr, left, j);
    if (i < right) QuickSort(arr, i, right);
}

第五章:散列表

  • 字典结构
  • 填装因子:散列表包含的元素数/位置总数
  • 散列函数:隐射key到value(目标数组所存的位置)

第六章:广度优先搜索

  • 一种基于图的查找算法
  • 广度有限搜索适用于无权重的图,求最短路径
  • 适用问题:
    1. 从节点A出发,有前往B的路径吗?
    2. 从节点A出发,前往B的哪条路径最短?
/**
 * 使用队列实现 bfs
 * @param root
 */
private static void bfs(Node root) {
    if (root == null) {
        return;
    }
    Queue<Node> stack = new LinkedList<>();
    stack.add(root);

    while (!stack.isEmpty()) {
        Node node = stack.poll();
        System.out.println("value = " + node.value);
        Node left = node.left;
        if (left != null) {
            stack.add(left);
        }
        Node right = node.right;
        if (right != null) {
            stack.add(right);
        }
    }
}

第七章:狄克斯特拉算法

  • 适用于非负加权图,找出最短路径
  • 如果包含负权重,需要用贝尔曼-福德算法
public void DijkstraSearch(costs) {
	node = find_lowest_cost_node(costs);
	while node is not None:
		cost = costs[node]
		neighbors = graph[node]
		for n in neighbors.keys():
			new_cost = cost + neighbors[n]
			if costs[n] > new_cost:
				costs[n] = new_cost
				parents[n] = node
		processed.append(node)
		node = find_lowest_cost_node(costs)
}

第八章:贪婪算法

  • 贪婪算法给我的感觉就是求局部最优解
  • 不求最佳,追求近似最佳
  • 适用于处理没有快速算法的问题,几乎不可能解决的问题?
  • 这本书给了个例子:安排课程,每个课程有一定的时间,希望尽可能多的课程在同一个教室上
    贪婪算法的逻辑:找出时长最短的课程,上完后找市场第二短的课程。重复这样就能找到答案
    -每步都采取局部最优解,最终达成全局最优解(信不信由你
  • NP完全问题:旅行商问、集合覆盖问题。这些都要求我们计算出所有的解,没有快速解决的算法。用近似求解就算不错了。
    • 找出满足条件最多的目标
    • 重复这个步骤直到满足所有条件
      -如何判断问题是NP完全问题:
    • 元素较少时算法运行非常快,但元素数量的增加,速度变得非常慢
    • 涉及”所有组合“的通常是NP完全问题
    • 不能将问题分成小问题,必须考虑各种可能的情况
    • 问题涉及序列且难以解决
    • 问题涉及集合且难以解决

第九章:动态规划

  • 动态规划是一种思想,它没有公式,它给予的是一种使用网格能解决特定问题的想法
  • 通常解决于能将问题拆成离散子问题的
  • 每个单元格是一个子问题,我需要考虑的就是如何解决子问题
  • 问题案例:
    • 有限重量的背包偷东西,每个东西重量价值各不相同
    • 字符串相似度比较,有关最长公共子串(字符串里最长的连续对应位置相同的字符)和最长公共子序列(字符串里对应位置相同的字符数)
      |-|H|I|S|H|
      |F|0|0|0|0|
      |I|0|1|0|0|
      |S|0|0|2|0|
      |H|0|0|0|3|

第十章:K最近邻算法(KNN算法)

  • 适用于推荐算法,或者根据以往的特征,预测结果(回归)
  • 能否挑选合适的特征是KNN算法的成败
  • 创建推荐系统
    • 特征抽取 (选择合适的特征,转换为可比较的数字)
    • 回归 即预测结果
  • 适用案例
    • 判断水果是橘子还是柚子
    • Netflix推荐用户电影
    • 一般如果有N个用户,需要比较的邻居数为sqrt(N)
  • 计算相似程度,可以用距离公式,也可用余弦相似度
    • 对于两个不同用户,它们品味相似,但是有的打分给5分,有的通常只给3分
    • 如果用距离公式就不好比较,除非先进行归一化
    • 余弦相似度不计算两个矢量的距离,而比较它们的角度,更适合此类问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值