
算法笔记
五道口纳什
wx公众号/B站:五道口纳什
展开
-
np.unique 的实现
1. 简单实现import numpy as npdef unique(ar): perm = ar.argsort() aux = ar[perm] flag = np.concatenate(([True], aux[1:] != aux[:-1])) return aux[flag]if __name__ == '__main__': ar原创 2018-01-20 21:02:06 · 1477 阅读 · 1 评论 -
随机化算法
随机化算法(randomized algorithm)随机化算法(randomized algorithm)的运行时间不只依赖于特定的输入,而且依赖于所发生的随机数。对于快排而言,使用随机枢纽元(pivot),将获得 O(NlogN)O(N\log N) 的期望时间。原创 2016-10-12 12:54:58 · 1519 阅读 · 0 评论 -
递推公式与递归退出的条件
1. 二叉搜索树查找原创 2016-09-19 18:36:43 · 1885 阅读 · 0 评论 -
双指针(下标)的应用
算法与语言无关,指针是 C 语言的范畴1. 朴素字符串匹配def naive_matching(t, p): m, n = len(t), len(p) i, j = 0, 0 while i < m and j < n: if t[i] == p[j]: i, j = i + 1, j + 1 else:原创 2016-07-25 19:11:53 · 1428 阅读 · 0 评论 -
辨异 —— 算法
swap (&data[i], &data[j]) ;注意这里交换的是 i,j 位置上元素的值;交换的不是 i, j 两个下标;原创 2016-09-22 11:05:07 · 805 阅读 · 0 评论 -
CSU1323: ZZY and his little friends
Descriptionzzy养了一只小怪兽和N只凹凸曼,单挑的话每只凹凸曼都不是小怪兽的对手,所以必须由两只凹凸曼合作来和小怪兽战斗。凹凸曼A和凹凸曼B合作的战斗力为他们战斗力的异或值。现在由zzy从N只凹凸曼中选出两只来和小怪兽战斗。请问zzy能否选出两只凹凸曼使他们能够战胜小怪兽(他们的战斗力比小怪兽大)。原创 2016-09-22 09:29:14 · 941 阅读 · 0 评论 -
使用异或解题 —— 序列中仅出现一次的两个数
异或算法在算法求解中的妙用如果一个序列除了某个数出现一次(奇数次)外,其他数均出现两次(偶数次),最终全部异或的结果会是这个出现一次(奇数次)的数;如果一个序列所有的数均出现两次(偶数次),最终全部异或的结果会是 0;如果一个序列除了某 2 个数出现一次(奇数次)外,其他数均出现两次(偶数次),最终全部异或的结果一定不为 0;原创 2016-09-22 08:16:28 · 1118 阅读 · 0 评论 -
异或算法在算法求解中的妙用
最高级的算法依赖于数学理论。1. 异或基本性质a ⊕ a = 0;a ⊕ 0 = aa ⊕ 全1 = !aa ⊕ b = b ⊕ aa ⊕ b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ ca ⊕ b ⊕ a = b ⇐ b ⊕ (a ⊕ a) = b ⊕ 0 = b2. 一个数组里除了一个数字(出现奇数次)之外,其他的数字都出现了两次(出现偶数次均可)。请写程序找出这原创 2016-09-21 22:22:41 · 1410 阅读 · 0 评论 -
动态规划(制表法)模板及应用
1. 模板int cache[2500][2500]; // 初始化为 -1,memset(cache, -1, sizeof(cache));int someObscureFunction(int y, int x){ if (...) return ...; int& ret = cache[y][x]; if (ret != -原创 2016-09-08 17:38:04 · 1293 阅读 · 0 评论 -
动态规划 —— 求解通配符问题(wildcard)
从穷举法开始,一步步最终实现动态规划的解决方案。原创 2016-09-08 18:43:01 · 1041 阅读 · 0 评论 -
算法问题的求解 —— 变量的引入
是否已被访问:布尔型,visited[] 数组bool visited[100]; // 默认被初始化为 false1. 冒泡排序:布尔型 sorted 变量用于标识是否数组已全部排序原创 2016-09-20 22:43:20 · 1098 阅读 · 0 评论 -
分治法求解切割篱笆
转换为数学(形式)语言,给出保存有各木板高度的数组 h[⋅]h[\cdot],截取第 ℓ\ell 个木板到第 rr 个木板的长方形面积可用如下公式:(r−ℓ+1)⋅mini=rℓh[i]\left(r-\ell+1\right)\cdot \min_{i=r}^\ell h[i]原创 2016-09-07 13:04:30 · 1983 阅读 · 1 评论 -
循环不变式(loop invariant)
循环不变式是一种条件式(必须满足的条件,对循环而言是保持不变的,无论循环执行了多少次),循环语句没执行一次,就要求中间的结果必须符合不变式的要求。(1)进入循环语句时,不变式必须成立;(2)循环语句的循环体不能破坏不变式。也就是说,循环体开始循环时不变式成立,结束时也必须成立;(3)如果循环语句终止时不变式,依旧成立,那么至少说明,循环在保持循环不变式上没有犯错。原创 2016-09-27 18:25:11 · 7886 阅读 · 0 评论 -
动态规划的关键 —— 子问题 & 公式化
将问题的规模从 n ⇒ n-1(n/2,或者其他更小的规模) 就将原问题转化为了其子问题;公式化:公式化的关键在于对问题进行数学抽象,然后转换为数学语言。原创 2016-10-16 21:30:57 · 2093 阅读 · 0 评论 -
随机化算法(二)
随机化算法1. 随机化快排将数组元素划分为 3 个子数组:A:包含比枢轴元素小的元素;B:包含与枢轴元素相等的元素;C:包含比枢轴元素大的元素;定理1 设数组含 n 个不同元素,随机快速排序算法的期望比较次数:T(n)≤2nlnnT(n)\leq 2n\ln n也即 T(n)=O(nlnn)T(n)=O(n\ln n)(与确定型快排相一致)首先来考验算法执行的流程,原创 2016-11-08 00:57:27 · 1025 阅读 · 0 评论 -
移位运算与除法、取模运算
求一个数二进制形式 1 出现的次数:int bitCount(int n);原创 2016-10-18 15:53:28 · 3535 阅读 · 0 评论 -
分治法(divide & conquer)与动态规划(dynamic programming)应用举例
1. 数列快速求和和矩阵快速乘法原创 2016-09-06 10:36:36 · 1725 阅读 · 0 评论 -
数据结构的时间复杂度与空间复杂度、及相关证明
有向图无向图的时空复杂度原创 2016-10-17 18:21:49 · 2057 阅读 · 0 评论 -
内存、时间复杂度、CPU/GPU以及运行时间
FLOP/s,Floating-point operations per second,每秒峰值速度, 一个 MFLOPS(megaFLOPS)等於每秒一佰万(=10^6)次的浮点运算,一个 GFLOPS(gigaFLOPS)等於每秒拾亿(=10^9)次的浮点运算,一个 TFLOPS(teraFLOPS)等於每秒万亿(=10^12)次的浮点运算,一个 PFLOPS(petaFLOPS)等於每原创 2016-09-07 12:33:50 · 4416 阅读 · 0 评论 -
伪随机数的生成算法
1. 线性同余发生器原创 2016-10-12 15:37:42 · 2388 阅读 · 0 评论 -
同余定理在算法求解中的应用
1. 同余定理原创 2016-10-19 18:08:16 · 1821 阅读 · 0 评论 -
求 1~n 之间素数的个数
1. 筛选法筛选掉偶数,然后比如对于 3,而言,筛选掉其整数倍数;原创 2016-10-06 19:18:31 · 8402 阅读 · 0 评论 -
元素之和最接近 0 的区间(部分和)
也即有以正数和负数组成的数组 A[] 时,求数组中区间之和最接近 0 的区间。A[i]:-14, 7, 2, 3, -8, 4, -6, 8, 9, 11(i=0~9)A[] 中并没有区间和等于 0 的区间,但有与 0 最接近的区间 A[2] ~ A[5],其区间和为 1。找出这种区间的一种方法是,也是最直观的想法,搜索所有区间并计算个区间的和,通过比较求出最小值。原创 2016-10-18 23:26:13 · 1182 阅读 · 0 评论 -
部分和(partial sum)在算法求解中的作用
1. 部分和的引入 并非什么高级深奥的技巧,但却十分有用。假设按照降序排列 NN 个学生的考试成绩并保存到数组 scores[],现在想要编写求出从第 a 名到第 b 名成绩的函数 average(a, b),最简单的方法是,将 scores[a] 到 scores[b] 的乘积全部相加,然后除以 b-a+1。这种方法的循环次数最大会达到 O(N)O(N)。如果只计算 1 次平均值,这种时复杂原创 2016-09-09 17:31:10 · 5654 阅读 · 0 评论 -
位运算 —— 一个数二进制形式尾端为 0 的个数
所谓一个数二进制形式尾端为 0 的个数,比如对于 40 而言,其二进制形式为 101000,则其尾端为 0 的个数为 3,或者也可简单地返回 2^3 = 8;Java 语言的 Integer 类其实本身就提供了该接口,Integer.numberOfTrailingZeros(n);原创 2016-10-16 13:03:27 · 2161 阅读 · 0 评论 -
N 个互异数的数组的平均逆序数
N 个互异数的数组的平均逆序数为 N(N−1)/4N(N-1)/41. 简单证明对于任意的数的表 LL(5,8,9,6,4),以及其反序表 LrL_r(4,6,9,8,5),它们各自的逆序数分别为:6 ((5, 4), (8, 6), (8, 4), (9, 6), (9, 4), (6, 4)),4((6, 5), (9, 8), (9, 5), (8, 5))。原创 2016-10-04 10:05:00 · 2345 阅读 · 3 评论 -
插入排序(insertion sort)
循环不变式原创 2016-09-26 20:13:05 · 1138 阅读 · 0 评论 -
“冗余”的参数(变量) —— 提升访问的效率
增加了空间成本;一般在一个函数的接口中,形参之间是不能相互得出的(或者根据一个形参得出其他形参),也即编程原则上,“一种信息只利用一种形态保存”。但多余的参数,却无形中,为程序的实现带来了效率的提升。比如著名的旅行商问题,共 N 个城市(0 ~ N-1,进行编号);原创 2016-09-05 23:55:54 · 2510 阅读 · 1 评论 -
从大整数乘法的实现到 Karatsuba 快速算法
Karatsuba 快速乘积算法是具有独特合并过程(combine/merge)的分治算法(Karatsuba 是俄罗斯人)。此算法主要是对两个整数进行相乘,并不适用于低位数(如 int 的 32 位的整数)。Karatsuba 快速乘积算法首先将两个整数分别一分为二。例如,a 和 b 各位 256 位的整数,那么使用 a1a_1 和原创 2016-09-06 15:36:50 · 4200 阅读 · 0 评论 -
算法求解方法与思路的总结
1. 穷举搜索生成所有排列(permutation)生成所有组合(combination)生成 2n2^n2. 分治原创 2016-09-06 08:55:56 · 1001 阅读 · 0 评论 -
组合搜索(combinatorial search)在算法求解中的应用
1. 分治、动态规划的局限性没有合适的分割方式时,就不能使用分治法;没有合适的子问题或占用内存空间太大时,就不能用动态规划;此时还需要回到最基本的穷举搜索算法。穷举搜索(exhaustive search)会把生成答案的过程分为几个选择的过程,之后利用递归调用完成各个选择项,由此实现其目的。此时,所有子问题的答案和已完成答案的集合就是搜索空间(search space)。例如旅行商(TSP)问原创 2016-09-10 11:11:32 · 2190 阅读 · 0 评论 -
贪心算法求解问题的选择准则
贪心不贪心,是设计者说了算,也就是说,什么情况下是贪心的选择,什么情况下不是贪心的选择,由设计者自己定义。比如公交线路的选择,最优可以指定为,1. 时间最短,也可以是,2. 最少换乘;1. 活动选择问题(activity selection problem)某公司的一间会议室,在同一天内,被多个部门预约(预约在不同的时间段),那么最多能选出几个? 解决此类问题的贪心算法应该从最早结束的会议开始选原创 2016-09-10 10:24:24 · 1082 阅读 · 0 评论 -
常见问题与常见算法的时间复杂度
旅行商问题,比如某地有 nn(2≤n≤102\leq n\leq 10)个城市,推销员想从一个城市出发,访问所有大城市之后回到起始位置。、假定,此地恰有最多的 10 个城市,出发城市是固定的,下一站 9 种选择,再下一站 8 种选择,下下一站 7 种,等等。9!=3628809!=362880也即 n−1n-1 个城市的全排列为 (n−1)!(n-1)! 种;原创 2016-09-05 22:44:47 · 1359 阅读 · 0 评论 -
算法 Tricks(六)— if 条件分支的简化
考虑下面的三分支的定义式:f=⎧⎩⎨⎪⎪a,b,a+b,x>yx<yx=yf=\left\{\begin{array}{l}a,&x>y\\b,&x\lt y\\a+b,&x=y\\\end{array}\right.int f = 0;if (x >= y) f += a;if (x <= y) f += b; // 这样当 x原创 2016-09-09 22:46:13 · 1079 阅读 · 0 评论 -
棋盘类游戏编程
将对图案的操纵,转换为对变量(基本类型,二维数组)的操做;0. 棋盘坐标系与棋盘元素的表示 简单的L型图案(三个单元格)在棋盘中心位置的形态为:const int coverType[4][3][2] = { {{0, 0}, {1, 0}, {0, 1}}, {{0, 0}, {1, 0}, {1, 1}}, {{0, 0}, {0, 1}, {1, 1}},原创 2016-09-05 00:02:33 · 2318 阅读 · 0 评论 -
算法 Tricks(五)—— 将一个序列量化为何值时平方误差最小
设数列为 A[],区间在 [a, b],设使量化后误差平方最小的数值为 m,则误差平方关于 m 的函数可以写作如下形式原创 2016-09-09 17:14:57 · 1025 阅读 · 0 评论 -
算法问题的解决 —— 预测答案结构(限制答案的形式)
对于一些存在数量庞大的子问题的问题,我们可以强制预测答案结构。所谓预测答案结构,即是寻找可行的答案中可能存在的 pattern,也即规律。比如序列的量化问题,将小于 1000 的自然数组成的序列量化成 s 个自然数组成的序列,且要求最终的误差平方和最小。比如,把序列{1 2 3 4 5}量化成{2 2 4 4 4}(s = 2)。该问题其实蕴含着丰富的子问题,对着这种具有庞大子问题的问题,我们就可以原创 2016-09-09 16:07:56 · 1052 阅读 · 1 评论 -
算法 Tricks(四)—— 判断序列中的字符/数值是否交替出现
比如:353, 54545,数字都是交替出现的:bool alternate = true;for (int i = 0; i < M.size(); ++i){ if (M[i] != M[i%2]) alternate = false;}i = 0,1,2,3,4i%2 = 0,1,0,1,0,在 0 的位置上的元素是否相等,在 1 位置上的元素是否原创 2016-09-09 12:08:18 · 917 阅读 · 0 评论 -
动态规划求解序列问题(LIS、JLIS)
1. 最长递增子序列 不要求位置连续;要求大小严格递增(strictly increasing)原创 2016-09-09 08:19:35 · 1228 阅读 · 0 评论 -
最优子结构(optimal substructure)
最优子结构是依赖特定问题和子问题的分割方式而成立的条件。各子问题具有最优解,就能求出整个问题的最优解,此时条件成立。比如求广州到北京的最短距离,假设这个路径必经过中间的南京,那么先把路径分割为(广州,南京)和(南京,北京)。分别求出子路径的最短距离然后再连接,就可以得到广州到北京的最短路径。因此,寻求最短路径的问题可以利用子路径的最优解获得整个问题的最优解。这样就可以证明,最短路径具有最优子结构。反原创 2016-09-09 00:24:10 · 23003 阅读 · 1 评论