
算法
一只老风铃
欣于所遇,暂得于己,快然自足。
-
原创 单源最短路径算法
对于单源最短路径算法,最为著名的为基于贪心策略的dijkstra,其维护一个从开始点到所有点的Dis[]数组,每次选取剩余点中距离源点最短的点,加入到已访问集合U中,同时更新源点到剩余点集合V中的点的Dis[]数组。题目描述在一个有向无环图中,已知每条边长,求出1到n的最短路径,返回1到n的最短路径值。如果1无法到n,输出-1输入5,5,[[1,2,2],[1,4,5],[2,3,3],[3,5,4],[4,5,5]]输出9核心公式: dis[index]+map[index][.2021-03-01 05:10:2828
0
-
原创 Manacher算法:避免从1开始
问题引出给定一个字符串str, 返回str中最长回文子串的长度str=“123”。其中的最长回文子串“1”或者“2”或者“3”,所以返回1。str=“abc1234321ab”。其中的最长回文子串“1234321”,所以返回7。如果str的长度为N,解决原问题的时间复杂度都达到O(N).输入描述:输入为一个字符串str输出描述:输出一个整数表示最长回文子串的长度此类问题与KMP算法类似,都是字符串匹配算法,KMP算法利用模式串的next数组,避免重复计算,其核心思想是:当匹配失2020-12-04 02:16:1045
0
-
原创 Leetcode 堆排序
堆是完全二叉树,即对于一个节点k 其孩子节点为2k+1 2k+2 (存在孩子节点情况下) 满足任意一个节点值大于(或小于)其孩子节点值,在建立和调整堆的过程包含两大操作:shift_up:向上调整,通常用于末尾添加一个新节点后,向上方向移动若干个位置,即不断判断其父亲节点是否更小,若是:交换 shift_down:向下调整,当根节点删除后,需要在根节点补充一个(通常是末尾),该元素需要下沉到合适位置,基本策略是:若当前节点比左右孩子节点都大,无需调整。 否则,找到孩子节点的最大值,与当前...2020-10-02 10:01:2145
0
-
原创 关于约瑟夫环的递归思路
有n个人,编号为1~n,从第一个人开始报数,从1开始报,报到m的人会死掉,然后从第m+1个人开始,重复以上过程。在死了n-1个人后,问最后一个人的编号是?解法一模拟:采取一个dead[]数组,每次从一个没有死的人开始,活着的人依次报数(那么需要跳过dead[i]==true的人),到m处那个人去世同时计数num++ 当杀死num==n-1时,返回dead[]数组中为false的人下标+1易错点(下标)解法二递归:将n个人排开,第m个人奖去世=》子问...2020-09-17 23:03:4638
0
-
原创 二分图的最大匹配-解决匹配问题
题目描述题目描述若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的N(N为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。输入:有一个正偶数N(N≤100),表示待挑选的自然数的2020-09-11 15:33:12232
0
-
原创 动态规划 分类01背包问题
题目描述物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:主件 附件 电脑 打印机,扫描仪 书柜 图书 书桌 台灯,文具 工作椅 无 如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。在不超过N元(可以等于N元)的前提下,使每件物品的价格与重...2020-09-07 12:04:0350
0
-
原创 算法 DFS
题目描述题面n-1n−1条道路连通的nn座城市,城市两两之间有且只有一条路径,每条都道路都有一个权值ww。现在城市之间要建立通讯网络,两座城市之间通讯质量取决于链路所经路径的权值和,权值和越大则链路的通讯质量越高。一条路径被破坏后,经过这条路径的所有通讯线路均被破坏。牛牛想知道哪条道路一旦被破坏,对整个城市通讯网络的影响最大。输入第一行一个正整数nn。接...2020-04-23 11:53:2789
0
-
原创 动态规划 最大乘积
【问题描述】Given a rope whose length is n(n is an integer), please cut the rope to m parts(each part’s length is an integer) to get the maximum product of the length of each part Ql1+l2+..+lm=n l1 ∗ ...2020-01-08 20:11:46285
0
-
原创 动态规划 二叉树选点
【问题描述】You are given a binary tree, and each node in the tree has a positive integer weight. If you select a node, then its children and parent nodes cannot be selected. Your task is to fifind a se...2020-01-08 19:21:4478
0
-
原创 动态规划 01背包拓展
【问题描述】There is a server which has the disk space ofMand the memory ofN. Given some tasks, thei-th task needs the disk space ofXiand the memory ofYi, and it can serveUiusers. Design an algor...2020-01-06 20:18:1459
0
-
原创 动态规划 金币配置
【问题描述】给定一系列的整数金额的硬币(数量足够),给定一个金额N,问有多少种组配方案?例如,面值为1和面值为2的硬币,组配金额4,方案如下:1 1 1 1 2 1 1 2 2共三种方案。【求解思路】将所有硬币按照面值大小从小到大排列,假设有m种不同面值的硬币,那么最终组配方案可以分为m类:使用前1种硬币组配方案 使用前2种硬币组配方案 使用前3种硬币组配方案 ...2020-01-06 18:03:39130
0
-
原创 动态规划 二叉搜索树的种类
【问题描述】给定从1到n的n个编号的节点,问这些节点可以构成多少种不同的二叉搜索树?当n=1时,只有1种当n=2时候,有2种以1为根节点 以2为根节点当n=3时,有3大类,共5种以1为根节点 以2为根节点 以3为根节点【求解思路】对于1到n个节点,其最终的二叉搜索树的种类可以分为n大类;即以1为根节点以2为根节点以3为根节点........2020-01-06 15:36:25157
0
-
原创 分治算法 凸多边形的划分
【问题描述】给定一个n边形,可以用不交叉的直线将多边形划分成多个三角形,给多边形顶点从1到n编号,问有多少种划分方法?显然;当n=3时,有一种划分方法当n=4时,有两种划分方法当n=5时,有5种划分方法........【求解思路】仅仅考虑和两点连成的边,那么在最终的划分中必定属于一个划分三角形的2个顶点。依据第三个顶点进行分类讨论:若第三个顶点为 ...2020-01-05 20:25:56305
0
-
原创 线性规划 原问题与对偶问题
在线性规划中,通过对原目标函数引入拉格朗日乘项,转化为求解对应新函数的优化问题2019-12-15 21:16:541374
0
-
原创 线性规划 单纯形算法实现
【问题描述】DescriptionSuppose you will recruit a group of volunteers for a coming event. It is estimated that this event will take N days to complete, and the i(th) day needs at least Ai volunteers. Th...2019-12-16 21:21:26310
2
-
原创 线性规划 单纯形算法实例
例:解最优化问题:min -x1-x22x1+x2<=12 x1+2x2<=9 Xi>0 ,i=1,2,3,4【1】改写成标准形式,引入松弛变量2x1+x2+x3=12 x1+2x2+x4=9 Xi>0,i=1,2,3,4列出单纯形表: X1 X2 X3 X4 b X3 2 1...2019-12-13 21:27:3888
0
-
原创 动态规划 多重01背包及空间开销优化
先考虑传统01背包问题:给定N个物品的权重和价值,如何选择部分物品放入最大容量W的背包中,以获得最大总值?其转移方程是: dp[i][j]表示前i件物品选择一些装入j容量包能获取的最大价值那么 dp[i][j]=max{ dp[i-1][j],dp[i-1][j-w[i]]+value[i] }也就是考虑第i件物品放入或者不放入背包,这两者中取最大值如何填充这个dp数组? 依次...2019-12-03 11:50:5056
0
-
原创 二叉树 判断一颗二叉树是否是另一颗树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构) 思路:1 判断A B根节点是否相等,若相等,判断A B左右子树是否是 父子结构关系 若都成立 返回true2 若不相等,那么递归到A的左右子树 判断B是不是A的子树的子结构 树结构: truct Tree...2019-02-17 11:11:22362
0
-
原创 算法 判断一个字符串是否是数字字符串
给定一个字符串,判断是否符合数字串(包括整数,小数,科学计数)如串"+120","5e20","-1243","3.1416"和"-1E-16"表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。不考虑正则表达式的标准做法,一般情况下的思路:遍历每一个字符,寻找不符合条件的情况对于+ -第一次出现位于开头,或者E之后 第二次出现(...2019-03-24 09:53:02454
0
-
原创 运算符 &&短路执行
intmain(){inta=1,b=2,m=0,n=0,k;k=(n=b<a)&&(m=a);printf("%d,%d\n",k,m);return0;}最终结果 0 0即(n=b<a)判断为0后不再执行m=a2019-08-31 18:34:3980
0
-
原创 算法 并查集与路径压缩
问题描述: 给定武林中人的数目,以及一组关系 若a与b有关系,那么a b属于同一帮派,关系可以传递 问这群人中总共组合成多少个帮派?思路: 并查集经典应用: 通过,查询,合并等操作 实现细节: 初始化一个人一个帮派,每合并一次 sum--案例输入: 10 9 1 2 1 3 1 4 1 ...2019-09-05 10:57:5983
0
-
原创 算法 图的最小生成树算法
最小生成树的Kruskal算法采取贪心策略即将图的各条边按照权值大小排序,依次从最小的边开始加入最小生成树但是加入前需要确认加入的边不会使得原先构成环基本思路:初始化每个顶点为单独一个集合,每加入一条边后,合并边所在的2个顶点所属集合每次加入边时需要确认边2边所属顶点集合不同采取并查集实现集合合并与快速查询,采取路径压缩加速并查集void UFSet()//初始化{...2019-09-07 11:31:3659
0
-
原创 算法 海量数据中第K大的数
针对大量数据,并且数据还在不断增长的情况,返回第K大的数(如排行榜维护)思路,采取最小堆,初始化堆放入K个元素,之后每来一个数,若数比堆顶元素大,则删除堆顶元素,并替换新的数否则,不做操作#include <iostream>#include<queue>using namespace std;int main(){ priority_queue...2019-09-10 14:28:24222
0
-
原创 快速排序 寻找第K大的数
对于海量不确定数据,可采用维护大小为K的最小堆不断更新前K大的数但对于数量有限的数组,可采用快速排序的思想寻找第K大的数,时间复杂度为O(lgN)即快排之后,若K刚好为基准点下标,那么返回基准点处的值若K小于基准点,那么在前部分序列中递归查找若K大于基准点,那么在后部分序列中递归查找int Partition(int low, int high, int a[]){ ...2019-09-15 10:34:18284
0
-
原创 归并排序 求解显著逆序对
求解逆序对,可以采取归并排序的方法即当前半部分a[i]大于后半部分a[j]时,结果res+=m-i+1(其中m-i+1表示前半部分a[i]及其之后所有元素与a[j]构成逆序对)显著逆序对 a[i]>3a[j+1]具体思路,当a[i]>a[j]时进一步从此开始向后寻找到一个a[k]>3a[j]那么res+=m-k+1;注意可能出现a[j]<a[...2019-09-15 14:02:17113
0
-
原创 算法 扑克牌顺子
一副牌中有4个大小王(数字0表示,其它牌为1~13),可以代表任何牌,现在抽取5张牌,判断能否组成顺子传统思路:统计0的数目,然后其它牌排序,判断是否有间隙,且间隙能被0填充进阶思路:统计每张牌出现数目,若超过1次,必定不能组成顺子记录遍历每张牌途中的最大最小值(区间) 0跳过若最后 max-min<5 说明一定能组成顺子class Sol...2019-03-23 09:46:52339
0
-
原创 DFS 求运动的范围
地上有一个矩阵方格。一从坐标0,0的开始移动,每一次只能向左,右,上,下四个方向移动一格, 但是不能进入行坐标和列坐标的数位之和大于k的位置。 当k=18时,能够进入(35,37),因为3+5+3+7 = 18。 它不能进入(35,38),因为3+5+3+8 = 19。求一共可以访问的坐标数目思路:设置一个visit访问数组,从(0,0)开始每遇到一个节点,设置为已访问同时...2019-03-13 16:54:5545
0
-
原创 链表 寻找链表中环的起点
给定一个单链表,若该链表有环,返回环的起点,若没有,返回NULL基本思路:每遇到一个节点,计数器++ ,当遇到访问次数为2时,返回该节点,否则在循环结束前还没有找到,则返回NULLclass Solution {public: ListNode* EntryNodeOfLoop(ListNode* pHead) { if(!pHead) ...2019-03-13 15:50:17239
3
-
原创 字符串 通配符匹配
问题描述:通配符匹配通配符 ? 表示可以替换一个任意字符 通配符 * 表示可以替换一个 长度任意的字符串 或者替换空a*b? 可以匹配: acdbfdbf abc 现给定通配字符串s1 判断s2 是否满足匹配思路:采用动态规划 dp[i][j]表示S1前i长度部分与S2前j部分是否匹配对于dp[i][j]——s1[i]为*表示,该处可以为任意字符串 ...2019-02-27 15:52:271937
0
-
原创 算法 最大连续子序列的和
给一个数组,返回它的最大连续子序列的和。{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。O(n)时间复杂度的简洁解法class Solution {public: int FindGreatestSumOfSubArray(vector<int> array) { ...2019-02-17 12:36:55277
0
-
原创 算法 浮点数的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。思路 分为2大类 exponent小于0 exponent大于0 进一步细分exponent为奇数或偶数 采用递归下降计算法 fun(base,exponent)=fun(base,exponent>>1) 采用右移代替除2 另外分类...2019-02-17 11:30:24457
0
-
原创 数组 数组中超过一半的数字
问题描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。思路:对数组进行排序取数组的中位数(size/2处)若该数与第一个数字或最后一个数相等那么找到了该数否则不存在 返回0 class Solutio...2019-02-17 11:24:3492
0
-
原创 二叉树 层次遍历
给定一颗二叉树,依次从根节点一层一层返回节点基本思路:利用队列模拟这一过程根节点入队列取队列头节点若该节点还有左右节点 入队列之道队列为空二叉树结构struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : ...2019-02-17 11:20:2871
0
-
原创 二叉树 二叉树最近公共祖先
给定一颗二叉搜索树 2个节点,求2个节点的最近公共祖先思路:如果2个节点均大于根节点的值,那递归在右子树寻找 如果2个节点均小于根节点的值,那递归在左子树寻找 如果刚好一大一小于根节点的值,那么返回该根节点Node* Get(Node* root,Node* p1,Node* p2){ if(root==NULL || p1==NULL || p2==NUL...2019-02-21 23:58:57625
0
-
原创 二叉树 层次交替遍历二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。思路:层次遍历采用队列模拟开始 根节点入队列开始一个循环,每次出队列一个元素,访问该值若该节点 左右子节点不为NULL 放入队列尾部循环直到 队列为空——如何交替一行一行输出 一开始队列的长度为size表示上一层节点数目 每次控...2019-02-21 23:47:18185
0
-
原创 位运算 数组中出现一(两)次的数字
一个整型数组里除了一个数字之外,其他的数字都出现了偶数次。请写程序找出这个只出现一次的数字。思路:位运算对于相同的2个数 异或运算结果是0 那么出现偶数次的数字按位异或的最终结果是0而0与任何数做异或运算 结果还是那个数由位运算交换律可知 对数组所有数字做位运算的结果就是只出现一次的那个数字 //该方法找到数组中只出现一次的那个数 int find(vector&...2019-02-21 23:24:3560
0
-
原创 滑动窗口算法二 和为S的连续正数序列
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序思路:设定一个滑动窗口,左边left 右边right初始化 left=1 right=2那么这个窗口内的值和Sum为(right+left)*(right-left+1)/2比较Sum与S的大小关系如果Sum=S 那么符合条件的答案之一 l——left++ right++ 因为...2019-02-21 22:53:2578
0
-
原创 滑动窗口算法一 和为S的两个数
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。 暴力法思路:2个指针指向i j分别指向前后2个数字 i从0开始直到size-1j从i+1开始 分析和是否为S若为S 判断与之前最小乘积关系 vector<int> FindNumbersWithSum(vector<i...2019-02-21 22:28:3652
0
-
原创 算法 把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。思路:对于2个数字如 3 31 先将其转成字符串 拼接 直接比较字符串大小 313<331 所以 31排在3前面static bool fun(int a,int b) { ...2019-02-23 19:39:2952
0
-
原创 算法 不用+ - * /计算2个数的和
求两个整数之和,不使用+、-、*、/四则运算符号。思路:换算成二进制,两个二进制相加 为对应的按位异或 进位为对应的按位与运算 不断重复直到进位为05+7=12第一步:相加各位的值,不算进位,得到2。 第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位...2019-02-28 21:04:28237
0