算法基础
乐行僧丶
这个作者很懒,什么都没留下…
展开
-
递归逆序和正数输出正整数
正序输出#include <bits/stdc++.h>using namespace std;void print(int x) { if (x == 0) return; print(x/10); cout << x%10 << " ";}逆序输出#include <bits/stdc++.h>using namespace std;void reversePrint(int x) { if (x == 0) { retu原创 2020-11-15 16:24:14 · 614 阅读 · 0 评论 -
BF算法-串匹配算法
串的模式匹配:暴力算法,时间复杂度为O(n)。#include <bits/stdc++.h>using namespace std;// 返回第一次匹配到的位置int bf(char *s, char *t) { int i=0,j=0,k=0; while (i < strlen(s) && j < strlen(t)) { if (s[i] == t[j]) { i ++, j++; } else { j = 0; // 模式串原创 2020-11-11 10:51:08 · 166 阅读 · 0 评论 -
层序遍历求树的深度
#include <bits/stdc++.h>using namespace std;struct TreeNode { int val; TreeNode *left, *right;};void dfsGetDepth(TreeNode *root, int &x) { if (!root) return; queue<TreeNode*> q; q.push(root); while (!q.empty()) { int原创 2020-11-09 21:20:30 · 582 阅读 · 1 评论 -
最长公共子序列(dp)
f[i][j]class Solution {public: int longestCommonSubsequence(string a, string b) { }};原创 2020-10-30 09:17:32 · 141 阅读 · 0 评论 -
多机调度问题(贪心)
有n个任务,m台机器,n>m,每个作业i可以选择一台设备进行加工,加工时间为ti,每台机器同时只能加工一个作业,且不可中断。实现作业调度,使得n个作业的等待时间最短。样例输入:6 32 5 13 15 16 20样例输出:28贪心策略:优先处理花费时间长的任务,这样可以减少短任务的等待时间实现:#include <bits/stdc++.h>using namespace std;const int N=10010;int t[N]; // 存储任务所需要时间原创 2020-10-28 12:23:56 · 1271 阅读 · 0 评论 -
输出二叉树中值为x的祖先
struct node { int val; node *left, *right;};// 返回值判断二叉树中是否含有x// 含有x并且在子树中 则当前节点是一个祖先// 含有x但是就是当前节点的值 则直接返回到上一层调用bool ancestor(node *root, int x) { if (!root) return false; if (root->val == x) return true; if ((root->left && root-&g原创 2020-10-24 22:59:35 · 494 阅读 · 0 评论 -
二叉树的宽度
算法思想:用一个w维护当前二叉树的宽度,使用层序遍历的方式,每次入队后更新w的值。#include <bit/stdc++.h>using namespace std;struct TreeNode { int val; TreeNode *left, *right;};int width(TreeNode *root) { if (!root) return 0; queue<TreeNode*> q; q.push(root); int w = 1;//原创 2020-10-14 02:10:59 · 333 阅读 · 0 评论 -
并查集(路径压缩)C++实现
class UnionFind {private: int *father; int count;public: UnionFind(int n) { this->count = n; father = new int[n]; for (int i=0; i<n; ++i) father[i] = i; } ~UnionFind(int n) { delete[] father; } // 查找索引为x的节点的父亲节点的索引 int find(int x) {原创 2020-10-07 22:16:43 · 261 阅读 · 0 评论 -
一维数组&二维数组&对称矩阵&三角矩阵&三对角矩阵地址的计算
一维数组的地址计算设每个元素的大小是size,首元素的地址是a[1],则a[i] = a[1] + (i-1)*size若首元素的地址是a[0]则a[i] = a[0] + i*size二维数组的地址计算 (m*n的矩阵)行优先设每个元素的大小是size,首元素的地址是a[1][1],则a[i][j]?分析:a[i][j]位于第i行,第j列。它之前有i-1行,在第i行它之前有j-1个元素。即a[i][j] = a[1][1] + [n*(i-1) + (j-1)]*size三维数组的地原创 2020-10-07 20:39:23 · 8522 阅读 · 3 评论 -
kmp算法
Kmp算法是一种效率极高的串匹配算法,适用这样的场景,在给定文本串text中查找是否含有指定的模式串pattern。效率高的原因:利用部分匹配的信息,将已经匹配到信息存入next数组。本质上我觉得还是空间换时间的思想。类似的有求最大回文串长度的manacher算法。时间复杂度O(n+m)最长公共前后缀next数组的求解 next数组可以称之为prefix table,前缀表。next[i]表示的最长公共前后缀中前缀的最后以为下标(在数组中的位置)。对于任意字串s[0…i] 长度为k+1的前缀原创 2020-10-07 08:05:32 · 148 阅读 · 0 评论 -
01背包问题
有N件物品和一个容量为V的背包。放入第i件物品耗费的空间是vi,得到的价值是wi。求解将哪些物品装入背包可以使得价值之和最大。二维数组的暴力解法,未涉及空间优化。首先用子问题来定义状态,f[i][j]表示前i个物品放到容量为j的空间总价值最大。f[i][j]这个状态是由i-1推过来的,这里有两种考虑:第i中物品选择还是不选择,如果不选择f[i][j]==f[i-1][j],如果选择f[i][j] = max(f[i-1][j], f[i-1][j-v[i]]+w[i])。max(f[i-1][j],原创 2020-09-16 20:03:08 · 149 阅读 · 0 评论 -
单源最短路径--floyd算法
void floyd() { for (int k=1; k<=n; ++k) { for (int i=1; i<=n; ++i) { for (int j=1; j<=n; ++j) { if (i == j || i == k || j == k) continue; //避免不必要的判断 提高程序效率 else g[i][j] = min(g...原创 2019-11-27 22:12:31 · 479 阅读 · 0 评论 -
差分
题目描述:输入一个长度为n的整数序列。接下来输入m个操作,每个操作包含三个整数l, r, c,表示将序列中[l, r]之间的每个数加上c。请你输出进行完所有操作后的序列。输入格式:第一行包含两个整数n和m。第二行包含n个整数,表示整数序列。接下来m行,每行包含三个整数l,r,c,表示一个操作。输出格式:共一行,包含n个整数,表示最终序列。数据范围:1≤n,m≤100000,1≤l...原创 2019-11-20 20:33:44 · 179 阅读 · 0 评论 -
前缀和
问题描述,现在给定一个闭区间数组,求区间[l,r]的数据元素之和,询问m次,要求线性时间复杂度O(n)。比较常规的思路是使用循环遍历相加,但是一次循环的时间复杂度为O(n),m次询问最终的时间复杂度为O(n*m),显然是不满足要求的。我们可以采用空间换时间的策略,设置一个前缀和数组d,数组中任意位置i表示的是d[i] = a[1] + a[2] + … + a[i],经过这样的预处理,询问任意...原创 2019-11-20 19:28:01 · 182 阅读 · 0 评论 -
快速读入的技巧
在OJ上练习题目时,有些题目数据的输入非常大,即便是使用scanf()也会被卡常数,最后导致TLE。因此搜集网上的解决方案,常见的有以下两种:一、当数据量不是特别大的时间,此时可以关闭stdio的同步,使得cin,cout与printf, scanf一样快。核心代码:ios::sync_with_stdio(false)//此时注意在程序中不能再使用任何stdio的库函数,否则会造成混乱。...原创 2019-11-20 14:37:21 · 435 阅读 · 0 评论 -
求解逆序对的个数(由归并排序衍生出的O(nlogn)时间复杂度的算法)
逆序:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一、暴力做法int count(int *a, int n) { int res = 0; for (int i=0; i<n-1; ++i) { for (int j=1; j<n; ++j) { if (a[i] > a[j]) res ++; } ...原创 2019-11-19 11:55:40 · 601 阅读 · 0 评论 -
八皇后--回溯法
#include <bits/stdc++.h>using namespace std;const int N=8;int chess[N][N];int cnt = 0;void init() { for (int i=0; i<N; ++i) { for (int j=0; j<N; ++j) chess[i][j] = 0; }}v...原创 2019-11-09 15:47:34 · 134 阅读 · 0 评论 -
进制转换
P进制数转换为十进制数,采用按权展开相加。int p;//p进制int x;//p进制数字int product=1;//任何权值的0次幂均为1int y;//输出的十进制数字while(x != 0){ y = y+(x%10)*product;//(x%10)获取x的个位数字 product *= p;//获取下一位的权值 x /= 10;//去掉x的个位数...原创 2018-08-14 23:49:56 · 164 阅读 · 0 评论 -
全排列(permutation)
显然,对于具有n个元素的集合R,R={r1,r2,r3…rn},其排列方式有n!种。 如:R = {1,2,3},其全排列如下: 1,2,3 1,3,2 2,1,3 2,3,1 3,1,2 3,2,1 从上边的排列中可以看出规律,以集合中某一元素作为第一个数字,集合当中的其余数字做全排列。而其余数字组成的集合可以看作是子集合,子集合中的第一个元素作为第一个数字,子集合当中的其余数字...原创 2018-08-15 21:38:36 · 1013 阅读 · 0 评论 -
Hash初步(空间换时间的策略)
问题描述: 给定N个正整数,给定M个正整数。如N = {7,8,2,4},M = {8,2},查找集合M中的正整数是否在集合N出现过。暴力枚举:#include<cstdio>int main(){ int arr[N] = {7,8,2,4}; int brr[M] = {8,2}; for(int i=0;i < N;++i){ ...原创 2018-08-16 00:12:50 · 1311 阅读 · 0 评论 -
Codeup墓地 谁是你的潜在朋友
问题描述: “臭味相投”——这是我们描述朋友时喜欢用的词汇。两个人是朋友通常意味着他们存在着许多共同的兴趣。然而作为一个宅男,你发现自己与他人相互了解的机会 并不太多。幸运的是,你意外得到了一份北大图书馆的图书借阅记录,于是你挑灯熬夜地编程,想从中发现潜在的朋友。 首先你对借阅记录进行了一番整理,把N个读者依次编号为1,2,…,N,把M本书依次编号为1,2,…,M。同时,按照“臭...原创 2018-08-16 13:18:54 · 357 阅读 · 1 评论 -
fibonacci数列递归,动态规划,循环+递推三种方法的性能比较
斐波那契数列的定义 1.n==1 || n==2 A(n) = 1 2.An = A(n-1)+A(n-2)递归法:int fibonacci(int n){ assert(n > 0); //递归出口 if(n == 1 || n == 2){ return 1; } return fiboancci(n-1)+fib...原创 2018-09-02 14:08:27 · 1361 阅读 · 1 评论 -
数字黑洞
数字黑洞简介: 黑洞数又称陷阱数,是类具有奇特转换特性的整数。任何一个数字不全相同整数,经有限“重排求差”操作,总会得某一个或一些数,这些数即为黑洞数。“重排求差”操作即把组成该数的数字重排后得到的最大数减去重排后得到的最小数。—《互动百科》 下面看《算法笔记》上一个关于给定四位不完全相同的数字,演示到达:“数字黑洞的过程”。题目描述: 给定一个各位数字完全不相同的四位正整数,如果先...原创 2018-09-08 14:23:09 · 3612 阅读 · 0 评论 -
LeetCode 120.三角形的最小路径和(二维DP)
题目描述 给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。例如,给定三角形[ [2], [3,4], [6,5,7], [4,1,8,3]]自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。说明:如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加...原创 2018-09-03 12:13:52 · 498 阅读 · 0 评论 -
使用数组模拟队列、循环队列和栈
在一些考试题中以及笔试面试的过程中,在需要使用stack和queue的时候,可能被要求不能使用STL中相关的库函数,也就意味着我们需要使用纯C进行编程。但是如果在考试中或者笔试面试中,为了要使用栈和队列,而去写一个完整的数据结构是比较大费周章,况且在时间上也不一定允许,因此,使用数组来模拟栈和队列的实现是一种明智的选择,原因有两个:一、使用数组模拟队列和栈可以简化编程的复杂度,节省时间,比如在d...原创 2019-08-12 17:23:49 · 704 阅读 · 0 评论 -
二分查找的递归和非递归
二分查找的前提是数据有序,二分查找的性能十分优秀。时间复杂度为O(log2n)int binsearch(int arr[],int len,int value){ //low和high指向当前查找区间的两端,value为查找的关键字 int low=0; int high=len-1; int mid=(low+high)/2;//当前区间的中间 ...原创 2018-08-14 23:08:36 · 425 阅读 · 0 评论