markdown's People
markdown's Issues
Day 02 - 并查集
并查集
-
解决的问题的本质:连通性问题的判断
-
树形结构中,节点代表集合,边代表关系
- 根节点:全集
- 子节点:子集
Quick-Union 算法
以上图为例,讨论节点之间的联通关系。1:[4,3]
,从节点4开始,连接节点3。即将节点4对应的值变为3,也可认为节点4成为根节点,节点3为它的子节点。
随堂练习 -1
最终结果:
( 5 和 6 是根节点)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
1 | 2 | 4 | 4 | 5 | 5 | 6 | 6 | 9 | 7 |
图中有一个树遇见了极端情况——退化成一条链。
如何合并,用平均查找次数来判断()。
随堂练习 -2
最重要的特点:按质合并 + 路径压缩
例题一(朋友圈问题)
-
问题描述
-
源代码展示:
//71.cpp #include<iostream> using namespace std; #define MAX_N 10000 struct UnionSet{//结构体定义 int fa[MAX_N + 5] ; void init(int n){ for (int i = 1; i <= n; i++) fa[i] = i ; }//开始时,每个人的父节点就是其本身,此为赋值操作 int get(int x){ if (x == fa[x]) return x ; return get(fa[x]) ; //return (fa[x] = (x = fa[x] ? x : get(fa[x]))) ; } void merge(int a, int b){ fa[get(a)] = get(b) ; } };//并查集算法 UnionSet u ; int main(){ int n ,m ; cin >> n >> m ; u.init(n);//完成对每个节点的赋值(将其父节点的值表示出来) for(int i = 0; i<m ;i++){ int a,b,c ; cin >> a >> b >> c ; switch(a){ case 1 :{ u.merge(b, c) ;//对于新增信息构建相应的树(相应并查集) } break ; case 2 :{//判断两人是否属于一个朋友圈 cout << (u.get(b) == u.get(c) ? "Yes" : "No") << endl ; } break ; } } return 0 ; }
例题二(猜拳问题——带权并查集)
- 问题描述:
-
问题分析:
因为是猜拳的特殊问题,可以想到如下情况:
a->b->c->d->e->f
(a能赢b,b能赢c,c能赢d;同时,a会输给c,a会和d打平手)可以得知,胜负关系是循环的,用不同的权值来表示不同的输赢关系:0平,1赢,2输
-
源代码展示:
//72.cpp #include<iostream> using namespace std; #define MAX_N 10000 struct UnionSet{//结构体定义 int fa[MAX_N + 5] ,val[MAX_N + 5];//记录父节点以及权值的数组 void init(int n){ for (int i = 1; i<= n ;i++){ fa[i] = i ; val[i] = 0 ; }//初始时,每个节点均是自己的父节点,且权值为0,意味自己与自己打平 } int get(int x){ if (x == fa[x]) return x ; int root = get(fa[x]) ; val[x] += val[fa[x]] ; val[x] %= 3 ; return fa[x] = root ; }//处理带权问题的部分 void merge(int a ,int b, int t){ int aa = get(a), bb = get(b) ; if(aa == bb) return ; fa[aa] = bb ; val[aa] = (val[b] + t - val[a] + 3) % 3 ; return ; } };//带权并查集算法 UnionSet u ; int main(){ int n, m ; cin >> n >> m ; u.init(n) ; for(int i = 0; i < m ;i++){ int a, b, c ; cin >> a >> b >> c ; switch(a){ case 1 :{ u.merge(b, c, 1) ; } break ; case 2 :{ if(u.get(b) != u.get(c)){ cout << "Unknown" << endl ; }//无法判定输赢的情况 else{ switch((u.val[b] - u.val[c] + 3) % 3){ case 0: cout << "Tie" << endl ; break ; case 1: cout << "Win" << endl ; break ; case 2: cout << "Loss" << endl ; break ; }//根据最终计算出来的权值来判断输赢 } } break ; } } return 0 ; }
Day 02 - 递归
Day 02
递归程序设计
一种技巧,程序调用自身
- 定义一个明确的语义信息
- 确定边界条件
- 针对于问题的
处理过程
和递归过程
- 结果返回
随堂练习 1
//6.func.cpp
//计算N阶乘
#include<iostream>
using namespace std ;
int f(int n){//定义函数
if(n<=1) return 1 ;//0和1的阶乘均为1
return n*f(n-1) ;//若n!=0||1,则需要递归
}
int main(void){
int n ;
cin >> n ;
cout << f(n) <<endl ;//由于返回值就是最终结果,因此直接cout
return 0 ;
}
辗转相除法
-
用于快速计算两个数字的最大公约数
-
用于快速求解
a*x + b*y = 1
的一组整数解证明过程: gcd(a,b) = gcd(b,a%b) a = x*d && b = y*d gcd(x,y) = 1 a%b = a - k*b = x*b - k*y*d = (x-k*y)*d
-
求解
a*x + b*y = 1
的分析a*x + b*y = 1 b*x + (a-k*b)*y = 1 a*y + b*(x-ky) = 1
-
使用辗转辗转相除法求解方程的具体算法实现
//7.gcd.cpp #include<iostream> #include<stdio.h> using namespace std; int gcd(int a, int b){ if(b == 0) return 0 ; return gcd(b, a % b); //return (b ? gcd(b, a % b): a); } int ex_gcd(int a,int b,int &x,int &y){ //&x,&y x,y的引用, 希望传出结果 if(b == 0){ x = 1; y = 0; return a ; } int r = ex_gcd(b , a%b, y , x); //假设有两个变量sx,sy(表示当前的X和Y的值) //x = sy ;y = sx + a/b * sy //从而将ex_gcd()中的参数确定 y -= a/b * x ; return r ; } int main(void){ int a,b ; while (cin >>a>>b){ int x,y,r ; r = ex_gcd(a,b,x,y) ; cout << "rest :"<< r << endl ; printf("%d * %d + %d * %d = %d\n", a, x, b, y, a * x + b * y ); } return 0 ; }
递归指数枚举
- 问题描述:
- 源代码展示:
//235.cpp
#include<iostream>
#include<stdio.h>
#define MAX 10
int arr[MAX + 5];//存放最终结果的数组
using namespace std;
void func(int k,int ind,int n,int *arr){
//k表示当前所在节点,ind表示当前可以操作的最小的数,n表示当前可以操作的最大的数,*arr指向存储数组
if(k != 0){//如果当前节点不是根节点
for (int i = 0;i<k;i++){
i == 0 || cout << " " ;
cout << arr[i] ;
}
cout << endl ;
}
for(int i = ind; i <= n; i++){
arr[k] = i ;
func(k + 1,i + 1, n, arr);
}//从根节点开始向下遍历,每一层遍历结束,就向下一层继续遍历
return ;
}
int main(){
int n ;
cin >> n ;
func(0, 1, n, arr);
return 0 ;
}
递归组合型枚举
- 问题描述:
- 源代码展示:
//236.cpp
#include<iostream>
#define Max 10
int arr[Max + 5] ;
using namespace std;
void func(int k ,int m,int ind ,int n,int *arr){
//ind表示当前可以操作(输出)的最小的数
//k 用来控制输出
if(k == m){
for(int i = 0;i<m;i++){
i == 0 || cout << " " ;
cout << arr[i] ;
}
cout << endl ;
return ;
}
for(int i = ind ;i<=n; i++){
arr[k] = i ;
func(k+1, m, i+1, n, arr);
}//递归主体
return ;
}
int main(){
int n, m ;
cin >> n >> m ;
func(0, m ,1, n, arr) ;
return 0 ;
}
表达式计算
- 问题描述:
- 问题分析:
- 源代码展示:
//266.cpp
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
#define INF 0x3f3f3f3f
int calc(char *str, int l, int r) {
int pos = -1, pri = INF, temp = 0;
for (int i = l; i < r; i++) {
int cur_pri = INF + 1;
switch (str[i]) {
case '(': temp += 100; break;
case ')': temp -= 100; break;
case '+':
case '-': cur_pri = temp + 1; break;
case '*':
case '/': cur_pri = temp + 2; break;
case '^': cur_pri = temp + 3; break;
}
if (cur_pri <= pri) {
pos = i;
pri = cur_pri;
}
}
if (pos == -1) {
int num = 0;
for (int i = l; i < r; i++) {
if (str[i] < '0' || str[i] > '9') continue;
num = num * 10 + str[i] - '0';
}
return num;
}
int a = calc(str, l, pos);
int b = calc(str, pos + 1, r);
switch (str[pos]) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
case '^': return (int)pow(a, b);
}
return 0;
}
int main() {
char str[1000];
while (cin >> str) {
cout << calc(str, 0, strlen(str)) << endl;
}
return 0;
}
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.