一、动态规划
背包问题:poj3624(经典01)、poj1837(01)、poj1276(多重)、poj2063(完全)
考虑前i位时的最优值dp[i]:poj3267(字典匹配)、poj1260(购买珍珠)
LIS:poj2533(最长上升子序列)、poj1836(凸字型士兵身高)
数字三角形:poj3176(数字三角形)
LCS:poj1159(添加字母变成回文串)(区间dp也可)、poj1080(基因序列最大相似度)
区间dp:poj1159、poj3280(变回文串的最小代价)
状态压缩:poj1185(炮兵阵地)
树形动规:poj1463(安排守卫)、poj3345(贿赂国家)、poj1947(删边得新子树)、poj2057(蜗牛找壳)、poj2486(吃苹果)
(树形动规通常和dfs相关联,首先在main函数中根据输入建好图,然后调用dfs,在dfs中对该层的dp数组初始化,然后就是dfs的for循环,在for循环中的第一步是接着往下dfs,第二步就是在dfs返回处开始dp的过程,也就是根据dp的变量范围进行for循环找最优解。)
二、搜索
深度优先搜索:poj1321(类八皇后)、poj2488(走马棋)、poj3009(冰球)、poj2531(两集合间距离)、poj2676(数独)、poj3620(dfs找最大连通分量)、poj3140(连通分量权值差)、poj3083(迷宫bfs+dfs)
(注意:dfs中如果设置了辅助变量,比如是否访问过vis[]/是否使被用过01[],或者dfs深度/步数,要在每次dfs后还原这些辅助变量。dfs在for循环之前先判断一下终止条件和剪枝条件。poj1321是简单的dfs,带有一个小剪枝,poj2488、poj3009都是带方向的dfs,有几条访问限制:是否出界;是否被访问过;是否已经有解;是否碰到障碍物;是否到达终点等等。poj2488是求第一次遍历出的解,所以dfs之前要判断是否已经有解了;poj3009是求所有解中的最优解,所以当遇到一个解时,记得还原辅助变量再return遍历其他解。poj2531类似剪枝dfs,同样需要注意辅助变量的恢复。poj2676与poj2488有相似之处,都是求出第一个解后就不再遍历去找其他解了,这种题需要设置一个flag标记是否已经有解,在dfs的for循环里要注意是否有解的标志,防止后续有解覆盖原解。poj3620也是带方向的dfs,map[][]辅助数组标记是否被搜索过,就是简单的dfs找最大连通分量。)
广度优先搜索:poj2251(三维地牢)、poj3126(素数变换)、poj3278(农夫追奶牛)、poj3414(倒水)、poj1426(找倍数)
(bfs经常用于求最短路或者题目中说有几种情况/几种操作是通常就暗示着用bfs/dfs,通常会设置node结构体,记录遍历的结点位置和步数/路长等信息,和bfs相似也需要一个vis[]数组记录是否访问过某结点。bfs过程就是出入队列的过程,将起始点压入,然后遍历从它开始往下走的几种可能性,将这些可能的结点中符合条件的压入队列,循环这个过程。poj2251判断是否越界、是否访问过、是否撞墙。poj3126没用到struct,因为只有一个分量,也就是现在得到的数是多少,所以用一个count[i]数组记录得到数字i时的变换次数即可,构建struct也可以,这道题算是二维的bfs,因为有4*10种情况需要遍历。poj3278同理只有一个分量,无需struct结点,本题需要判断是否越界和是否被访问过。poj3414多了一个输出步骤,就是输出最短路的遍历路径,此题中也就是按顺序输出操作。poj1426涉及数学知识同余模定理。)
简单搜索技巧和剪枝:poj1129(dfs无向图染色四色原理)、poj1416(字符串解答树)、poj1033(碎片还原)、poj3411(最短路)、poj1724(最短路)
(poj1129注意辅助变量的还原。poj1416切割字符串,这道题的特点在于要记录达到最优值的次数,所以在dfs的for循环前要进行是否得到解和得到最优解的次数的判断。poj1033是对每一个磁盘簇进行搜索,找到它对应的碎片并存入。poj3411就是dfs找最短路,不同之处在于它允许每个点被访问最多3次,只要将vis[]数组用来记录访问次数即可。poj1724利用了邻接表储存图里面的路。)
最优化与可行性剪枝(神奇剪枝):poj1011(拼木棍), poj1190(生日蛋糕)
记忆化搜索:poj1088(滑雪最长斜坡)、poj1191(棋盘分隔)、poj1691(画板上色)、poj3373(改数字变成倍数)
(不太明白出于什么原因在dfs搜索的题目中使用了记忆化数组帮助剪枝,为什么其他题没用?好像是由于这些题里面要从很多起点开始搜索,或者遍历的过程中会重复用到很多之前已经计算过的值,所以用记忆化数组剪枝。)
三、模拟题
poj3087、zoj3317、leetcode765(夫妇排座)
四、数据结构
字符串:poj3080(最长连续子串)、poj1936(最长子串)、poj1035(匹配)
排序:poj2388(快排、归并、堆排)、poj2299(归并)
(归并排序看poj2299即可,比较清晰明了)
Huffman树(优先级队列):poj3253、poj1862
(优先级队列默认从大到小排序,eg:priority_queue
并查集:poj1611(感染人数)、poj1182(食物链)、poj2492(交配)、poj1703(犯罪团伙)
哈希表:poj1840(五元方程)、poj1186(n元方程)、poj2503(字典查词)、poj2002(找正方形)、poj3274(奶牛属性)、poj3349(相同雪花)
(poj1840就是简单的hash,一对一映射,poj1186由于变元增加,我们需要设计多对一的映射,也就是说可能有多个值经过hash之后变成一个相同的值,然后用链接表储存相同哈希值的数。哈希的思想就是:当哈希值相同时才继续进一步搜索,提高了搜索效率。比如poj3274、poj3349,当两行的哈希值相同时,再进一步去判断两行的每一列是否都相等。哈希取模的模数要怎么选取?根据题中给出的n,也就是如果我们两两比较复杂度为O(n²)的那个n,在n附近选取一个质数。)
trie树(字母树、字典树、单词查找树)及AC自动机(构造trie图DFA的一种方法):poj2513(染色木棍首尾相接)
线段树:poj2828、poj2750、poj2777、poj2528、zoj1610、poj2886(没懂)
(利用线段树每个结点所代表的区间段来记录区间内的某些信息,染色题通常涉及到lazy,lazy标记的思想提高了搜索效率,当可以直接更新某个区间时给它一个lazy标记并return,表示现在可以先不继续往下更新子区间,但是当要更新的区间包含在当前区间内时,要将当前区间的lazy标记下传,并删除当前区间的标记,此时继续update而不是return)
树状数组:poj2299(逆序数)、poj3321、poj2352、poj1195
RMQ(区间最值问题):poj3264(区间最值)、poj3368(频数最值)、poj2452(最值的距离)
(dp思想,分两半子问题解决总问题)
KMP算法(没搞懂):poj1961、poj2406
单调栈:poj2559(直方图最大矩形面积)
(单调栈适合做的题目:要求每个点的左右界限,在弹栈进栈的过程中可以直接记录每个点的左右界限,方便遍历一次就得到想要的答案。比如poj2559,要求每个矩形的左右界限,也就是往左和往右到比自己矮的矩形之前,利用递增的单调栈,由于递增,所以新加入一个元素只要小于栈顶元素就要弹栈,弹栈时可以记录栈顶元素的右界限和当前新元素的左界限,当加入的新元素大于栈顶元素时,直接进栈即可。)
五、图论
最短路径:poj1125(经纪人传播消息)、poj2240(汇率赚钱多源)、poj1860(汇率赚钱单源)、poj1847(电车轨道闸口)、poj3259(虫洞)、poj2253(青蛙跳)、poj1062(聘礼)
(一共四种最短路径算法:floyd、djkstra、bellman-ford、spfa。poj1125讲解了四种。poj2240、poj1860不能用dijkstra,其他三种都可以。poj1847、poj2253、poj1062主要讲解dijkstra。poj3259是判断是否有负权回路的,用bellman或者spfa都可以。)
最小生成树:poj2485(高铁最长路段)、poj1258(光纤总长度)、poj1789(车牌衍生)、poj2349(哨所通信)、poj3026(迷宫)
(两种最小生成树算法:prim、krustral。prim是找距离点集最近的点添加到生成树中,krustal是找边集中最小的边添加到最小生成树中。当题中给出距离矩阵、图很稠密时用prim更方便一些,当给出稀疏图时用krustal。poj2458讲解了两种算法。poj1258、poj1789、poj3026prim。poj2349的解题与边密切相关,所以用krustal。)
拓扑排序:poj2585(屏幕窗口)、poj1094(大小排序)
(拓扑算法:建立有向图,记录出入度,找出有向图中入度为0的点,删去它以及它指出的所有边,如此循环。)
二分图的最大匹配:poj3041(消灭星星)、poj3020(基站覆盖城市)、poj1469(课程匹配课代表)
(匈牙利算法:dfs找增广路)
最大流的增广路算法:poj1459(耗电量总值最大)
(bfs找增广路,将增广路上的每条边都减去增广路上的容量最小值,反向边都加上容量最小值,最大流也加上这个容量最小值,最后找不到增广路时算法终止,此时得到最大流)
下面是二刷(Leetcode)
一、搜索
dfs:104(二叉树最大深度)、690(职员价值)、695(最大岛屿)、733(像素染色)、101(对称二叉树)、200(岛屿数)、329(矩阵最长路径)、399(除法)、802(找安全点)、17(手机键盘组合)、22(生成括号)、37(填数独)、39(可重复使用数字组合成目标和)、40(不可重复使用组合成目标和2)、87(搅乱字符串)、95(生成二叉搜索树)、100(判断两树相同)、98(判断二叉搜索树)、99(恢复二叉搜索树)、501(二叉搜索树最频繁点)、105(前序中序建树)、106(中序后序建树)、108(构建平衡二叉搜索树)
bfs:107(层次遍历二叉树)、101(对称二叉树)、111(二叉树最小深度)、102(层次遍历二叉树)、103(蛇形层次遍历二叉树)
二分查找:4(中位数)、35(升序数组找目标数字)、34(升序数组找目标数字范围)、33(旋转排序数组找目标数字)、81(带有重复数字的旋转排序数组找目标数字)、50(x的n次幂)、69(平方根)、74(二维矩阵找目标值)
回溯:44(通配符匹配)、46(无重复数字的全排列)、47(有重复数字的全排列)、51(N皇后的所有解)、52(N皇后解个数)、77(增序排列组合)、78(罗列子集)、90(罗列不重复子集)、79(搜索字符串)、93(恢复ip地址)、491(罗列升序子序列)
二、数据结构
数组:26(删除重复数字)、80(删除重复3次的数字)、27(删除指定数字)、41(最小缺失正数)、48(旋转二维数组)、54(按螺旋输出二维数组)、59(生成螺旋二维数组)、73(矩阵置0)、238(数组乘积)、674(LIA)
链表:2(链表相加)、19(倒数第n个)、21(合并两个链表)、23(合并K个链表)、24(交换链表结点)、25(以k个结点为一组交换链表结点)、61(旋转链表)、83(删除多余的重复元素)、82(删除重复出现的所有元素)、86(分隔链表)、92(反转链表段)
双指针:11(最大盛水量)、42(最大盛雨水量)、15(三数和为0)、16(三数和最近于目标)、18(四数和)、75(颜色排序)、88(合并升序数组)、713(数组乘积小于k)
数字:7(反转数字)、9(回文数)
字符串:657(机器人原点)、344(反转字符串)、557(反转句子里的单词)、521(最长不寻常子串)(注意:521不是最长非公共子串)、8(字符串转整型)、14(最长公共前缀)、28(strstr)、30(连续子串下标)、76(最小窗口子串)、38(数数并报数)、58(最后单词长度)、68(文本修正)
排序:349(交集非重)、350(交集可重)、242(颠倒字母)、4(中位数)、56(合并区间)、57(插入区间)
并查集:547(朋友圈)、684(判环)、200(岛屿数)、721(合并邮件账户)、130(X包围O)
哈希表:771(找宝石)、575(分糖果)、399(除法)、76(最小窗口子串)、697(数组的度)、336(回文对数)
集合set:500(键盘同行)、720(字典最长单词)
map&stack:332(行程规划)、1(两数之和)、3(最长不重复子串)、20(括号匹配)、32(最长有效括号长度)、30(连续子串下标)、36(有效数独)、49(颠倒字母的单词分类)、71(简化路径)、84(柱状图中的最大矩形面积)、85(二维矩阵中的最大矩形面积)、94(中序遍历二叉树)
trie:720(字典最长单词)、212
树状数组(BIT):307(数组更新求和)、315(右侧较小值个数)、493(倍数逆序对)
线段树:307(数组更新求和)(这道题是线段树模板题好好做一下)
出入度:732(线段重叠)
三、图论
拓扑排序:207(课程排序)、210(课程排序输出顺序)、329(矩阵最长路径)、310(图的最小深度)
二分图:785(判断是否是二分图)
最小路径:743(网络传播时长)、399(除法)
四、动态规划
考虑前i位时的最优值:746(爬楼梯最小代价)、70(爬楼梯方式个数)、53(子数组最大和)、198(抢劫不相邻房子)、303(子数组查和)、338(二进制数1)、647(回文串个数)、10(正则字符串匹配)、32(最长有效括号)、91(解码方式个数)、96(二叉搜索树个数)、300(LIS)、152(子数组最大乘积)、213(抢劫环形房子)、740(抢劫同值房子)、304(子二维数组查和)、639(解码方式个数)、646(二维LIS)、673(LIS个数)
区间长度dp:5(最长回文子串)、516(最长回文子序列)
二维dp:62(路径个数)、63(带障碍的路径个数)、64(路径和最小值)、72(编辑距离)、583(LCS)、97(交错字符串)、712(LCS距离)、174(地牢游戏)
树形动规:337(抢劫树形房子)
五、贪心法
55(跳一跳能不能跳到)、45(跳一跳最小跳数)、630(课程安排)、122(股票收益)
六、数学
29(不用除号实现除法)、31(下一个全排序)、43(字符串乘积)、60(第k个全排列)、65(合法数字)、66(数字加一)、67(二进制加法器)、69(平方根)、89(格雷码)、191(二进制1个数)、628(最大乘积)
七、其他
121(股票收益)、122(两次股票收益)、334(LIS)