【读书笔记】《挑战程序设计竞赛》

算法笔记 专栏收录该内容
5 篇文章 0 订阅

《挑战程序设计竞赛》


前言

坚持就是胜利,冲冲冲


一、蓄势待发–准备篇

1.5.1 算法复杂度

在这里插入图片描述
详细总结来源

1.6.1 O(nlogn)三角形问题

在这里插入图片描述

O(nlogn)方法:

  1. 将边按照从小到大顺序进行排序;
  2. 从大到小进行搜索,如果,edge[i],edge[i+1],edge[i+2]能构成三角形,即为周长对大的三角形;

原因:
三角形条件: A<B+C (其中A是最长的边);
要使得周长最长,B+C要尽可能的大;
排序后的B+C剩下边里面的最大,如果不满足,则没有边可以边满足B+C>A,即对A而言,不存在三角形;如果满足,则是最大周长的三角形;

练习 976. 三角形的最大周长

976. 三角形的最大周长

1.6.2 蚂蚁问题

在这里插入图片描述
在这里插入图片描述
蚂蚁交换方向就看成没有交换方向,反正都是蚂蚁向左爬和向右爬。具体代码如下:
在这里插入图片描述

1.6.3 抽签问题(四数之和)

在这里插入图片描述

问题描述:数组中是否存在: a+b+c+d = m
解决方案:看成前两个数之和与后两个数之和,利用二分查找,效率为(O(n^2logn)

练习 18. 四数之和

18. 四数之和

博客中使用:先排序;双指针(O(n^3)),回溯法(利用条件会剪枝)

二、初出茅庐–初级篇

2.1 “穷竭搜索”–暴力

穷竭搜索:将所有的可能性列出来,在其中寻找答案
递归:自己调用自己

数据结构:

栈Stack(LIFO):push;pop;peek;
队列Queue(FIFO):offer;poll;peek;

遍历方法:

深度优先遍历(DFS):深入;栈;(解数独)
宽度优先遍历(BFS):周围;队列 (最短路径,最少操作)

2.1.4 DFS–水洼的数量

在这里插入图片描述
思路:

  1. 八联通的则为水洼,需遍历一个单位附近的八个单位并将它们都改成’.’;
  2. dfs遍历到尽头,并将这些联通的W全部改掉;W连接的所有W都替换成了’.’;
  3. 直到图中不再存在W为止,执行dfs的次数即为水洼的个数。

练习 200. 岛屿数量

200. 岛屿数量

2.1.5 BFS–迷宫最短路径

在这里插入图片描述在这里插入图片描述

问题:N*M规格迷宫;起点S;终点G;墙壁#;通道.;寻找一条最短路径从起点到达终点

思路:

  1. 本题要求最短距离,可用 d[N][M] 数组保存距离,INF 初始化;将起点的距离设置成0;
  2. 将上下左右(可移动,是通道)的距离为当前点的距离+1,并且加入队列;
  3. 读取队列中节点,BFS遍历上下左右,直到遇见终点或者所有节点访问完成;
  4. 如果是遇见终点,即为最短距离;如果点访问结束,则不可达;

2.1.6 next_permutation(begin(nums), end(nums))

按照字典序给出nums数组的下一个排列顺序;
C++语言中可以用来跟方便的获取下一个排列顺序;java没有

练习 31. 下一个排列

31. 下一个排列

2.1.7 剪枝

暴力中,有时候解空间很大,深度DFS,有时候很早可以根据某些条件直接跳过,剪枝,来缩小解空间;

2.2 一直向前!–贪心

贪心:不断贪心地选取当前最优的策略
我的经验:主要是看问题贪心选择后能不能变成一样的贪心子问题

2.2.1 硬币问题

在这里插入图片描述
思想: 优先兑换面值大的硬币

2.2.2 区间问题

在这里插入图片描述
在这里插入图片描述

思想: 在可选的工作当中,每次都选择结束时间最早的工作

2.2.3 字典序最小问题

在这里插入图片描述

思想: 不断取S开头末尾较小的字符放在T末尾,如果相同,比较S与反转S’的字典序,选择较小方向字符的放在T末尾;

2.2.4 其他问题

在这里插入图片描述

思想: 向右遍历尽可能远的选择点,实现覆盖,这样最后获得最少的点
在这里插入图片描述
在这里插入图片描述

思想: 类比于哈夫曼树,最短的木板最远,最后加权路径和最小;
贪心:也可以利用2.4.1中讲的优先队列来获取最小的两个木板,将合并后的木板长度重新加入优先队列;

2.3 记录结果再利用–动态规划

动态规划(DP):记录结果再利用
我的经验:寻找递推关系式

2.3.1 背包问题

主要分为01背包问题和完全背包问题
在这里插入图片描述
递推关系式:
01背包问题:
需要上一行中的记录来实现新一行的更新;
其中竖直向上位置是上一行记录的直接成下移(实现上一行最大值的保留);
斜上角位置是需要加上物品价值(实现加入最大值得保留);两者比较取大
代码终极版本:
在这里插入图片描述
PS:j从后往前遍历;保证利用上面以及左上方的位置实现更新;保证左前方上一轮历史数据不被覆盖;很难,实际操作中容易操作不好;
在这里插入图片描述
参数范围发生了变化,其中w变得很大,按照之前的想法,不太可行;
需要交换 w 和 v; 最后在最后一行去寻找符合条件的w;具体代码如下:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完全背包问题:
需要上一行中的记录以及同行中前部分来实现新位置的更新;
其中竖直向上位置是上一行记录的直接成下移(实现上一行最大值的保留);
左前方位置是需要加上物品价值(此时考虑了之前加入的物品,实现多个物品加入);两者比较取大

代码终极版本:
在这里插入图片描述
PS:j从w[i]开始,即可以放下物品开始;从前向后遍历,先更新前面的值,因为后面要根据左前方的值进行修改;

2.3.2 最长公共子序列问题 LCS

在这里插入图片描述
在这里插入图片描述
PS:可以知道,

  1. dp[i+1][j] :(利用左前方)是 i 字符没有与 j 字符匹配,但 i 字符与 j 之前的字符有匹配关系,需要保留左边的记录;
  2. dp[i][j+1]:(利用上一行)是 i 字符没有与 j 字符匹配匹配,且 i 字符没有与 j 之前所有字符匹配,需要保留上一行的记录;
  3. dp[i][j]+1:(利用斜对角)是 i 字符与 j 字符匹配,匹配字符数量+1,且匹配的时候,dp[i][j]+1肯定最大,直接令dp[i+1][j+1] = dp[i][j]+1 就好

练习 1143. 最长公共子序列

1143. 最长公共子序列

2.3.3 多重部分和问题

在这里插入图片描述
在这里插入图片描述

练习 416. 分割等和子集

416. 分割等和子集
在集合中寻找是否满足集合总和的一半target;

主要算法是,寻找数,其和满足target,运用dp思想;
此时,重复的数看成了不同的物品(不同行,记录结果计算,更像01背包);
多重部分和问题中相同的数值,是同一个物品,在同一行,利用左边的历史记录进行计算;

2.3.4 最长上升子序列问题 LIS

在这里插入图片描述

练习 300. 最长上升子序列

300. 最长上升子序列
PS: 二分查找的方法不是很明白,还需要多寻思寻思

2.3.5 化分数(有点难,回头再看)

在这里插入图片描述
在这里插入图片描述

2.3.6 多重集组合数

在这里插入图片描述

2.4 加工存储数据–数据结构

2.4.1 堆

优先队列:实现如下操作的数据结构

  1. 插入一个数值;
  2. 取出最小值数值。

:高效实现优先队列操作的数据结构(大根堆,小根堆)(可以使用二叉树结构)
复杂度:跟树的深度成正比;两个操作均O(logn)完成
java中有:PriorityQueue优先队列;

PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11, new Comparator<Integer>(){ //大顶堆,容量11
	 @Override
	 public int compare(Integer a,Integer b){
	 	return b-a;
	 }
});

问题 Expedition 征程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.4.2 二叉搜索树

二叉搜索树:实现如下操作的数据结构。所有节点,都满足左子树上的所有节点都比自己小,而右子树的所有节点都比自己大。
复杂度:跟树的深度成正比;两个操作均O(logn)完成

  1. 插入一个数值;
  2. 查询是否含有某个数值;
  3. 删除某个数值。

java中,多练习list,map集合的使用

平衡二叉搜索树:任意节点的左子树与右子树高度差不大于1;(解决二叉搜索树退化问题)
二叉搜索树不平衡时,通过旋转来保持平衡

2.4.3 并查集(不熟悉)

并查集:用来管理元素分组情况的数据结构。可以高效的进行如下操作。

  1. 查询元素 a 和元素 b 是否属于同一组;
  2. 合并元素 a 和元素 b 所在的组。

复杂度:O(a(n))
在这里插入图片描述

结构:森林;不同的集合用不同的树表示;

合并:两棵树之间的合并
在这里插入图片描述
查询:从底向根遍历,判断是否同根
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
跳过,回头再来补,先通拉一边知识点

2.5 它们其实都是“图”

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值