常用算法思路总结

一、并查集

解决的问题类型:元素关系问题
总体分三部分:初始化(init)查(find)并(merge)

(1)简易的并查集

1、init()

创建一个一维数组,将下表作为当前关系人的编码,值为他的父节点。例如当前有N个人

int f[N+1];
for(int i=1;i<N+1;i++)f[i]=i;

2、find()

寻找当前这个人的 父节点

int my_find(int *f, int a)
{
	if(f[a]==a)return a;
	else return my_find(f,f[a]);
}

3、merge()

将a的根父节点改为b的根父节点

void meger(int *f,int a,int b)
{
	f[find(f,a)]=find(f,b);
}

具体问题训练为:leetcode:886.可能的二分法
思路:
操作1: 先创建人数2倍的并差集数组f[2*n+1],将每一个人的父节点都设置为自身。
操作2: 然后创建a人与b人以及他们的父节点da=a+n与db=b+n。
操作3: 查找a与b人的根节点是否相同,相同则返回false;不同则合并。
注意:合并是
a的根节点的父节点设置为db的父节点
b的根节点的父节点设置为da的父节点
原因
将a不喜欢的人b都分到同一个da的父节点下
将b不喜欢的人a都分到同一个db的父节点下

#define MAX_BUF_LEN 5000
int find(int *f, int a)
{
	if(f[a]==a)return a;
	else return find(f,f[a]);
}

void meger(int *f, int a, int b)
{
	f[find(f,a)] = find(f,b);
}

bool possibleBipartition(int n, int **dislikes, int dislikesSize, int* dislikesColSize){
	
	int *f =malloc(sizeof(int)*(2*n+1));
	//初始化并查集
	//操作1
	for(int i=1;i<2*n+1;i++)f[i]=i;
	
	//操作2
	int a,b,da,db;
	for (int i = 0; i < dislikesSize; ++i){
	 	a=dislikes[i][0];
	 	b=dislikes[i][1];
	 	da=a+n;
	 	db=b+n;
	 	//操作3
	 	if(find(f,a)==find(f,b))return false;
	 	meger(f,a,db);
	 	meger(f,b,da);
	 	printf("%d\n",a );
	} 
son  //1 - 2 - 3 - 4 - 5 - 6 - 7 - 8
fater//1 - 2 - 3 - 4 - 5 - 6 - 7 - 8

relaition //1,2
	 //1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 
	 //(6)-(5)-3 - 4 - 5 - 6 - 7 - 8

	 //1 , 3
	 //1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 //1.f=6->6.f=6 3.f=3
	 //6 - 5 -(5)- 4 - 5 -(7)- 7 - 8//6.f=3+4 3.f=5

	 //2,4
	 //1 - 2 - 3 - 4 - 5 - 6 - 7 - 8//2.f=5->5.f=5 4.f=4
	 //6 - 5 - 5 -(7)-(8)- 7 - 7 - 8//5.f=4+4 4.f=(2+4).f=6.f=7
	return true;
}

(2)优化并查集

在find()函数中,我们为了寻找到a1的根需要一直递归寻找,如果a2的父节点为a1,则寻找a2的根节点又重复了寻找a1的根操作,因此为了优化算法,我们将每一个数的父节点都指向他的根。

二、动态规划

有空再写

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ySh_ppp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值