设计一个算法的步骤:
Steps to developing a usable algorithm.
・Model the problem.
・Find an algorithm to solve it.
・Fast enough? Fits in memory?
・If not, figure out why.
・Find a way to address the problem.
・Iterate until satisfied.
总结:我们如何使用算法呢?首先,把问题建模,关键是要理解问题是什么?它包含什么元素?然后,找一个可以解决这个问题的算法。如果有很多可用的算法(比如排序算法就有很多),我们要如何选择呢?要空间还是要时间?想明白我们到底要满足什么,然后不断找出最佳解决方法。
动态连接算法:
准备——问题与问题建模:
Given a set of N objects.
・Union command: connect two objects.
・Find/connected query: is there a path connecting the two objects?
问题描述:现在有一堆对象(不重复),可以使用 ”连接命令“,连接相邻的两个对象,那么如何判断任意两个对象之间相连接呢?
问题建模:
1 .我们用0——n个数字代表对象的名称,(比如,int表示数组的索引)。
2.We assume “is connected to” is an equivalence relation:
・Reflexive: p is connected to p.
(任何一个节点与自身都是连接的)
・Symmetric: if p is connected to q, then q is connected to p.
(p可以连接到q,那么q也是可以连接到p的)
・Transitive: if p is connected to q and q is connected to r,then p is connected to r.(p连接q ,q连接r,那么我们说 p可连接r)
3.连接组件:
如下图,这样我们说总共有三个“连接组件”。
也就是说这个算法肯定有两个操作:union操作,queryConnected操作
举个例子,我们事先有如下0——9个数字(对象概念的抽象),执行union命令做连接:
union(4, 3)
union(3, 8)
union(6, 5)
union(9, 4)
union(2, 1)
那么现在 0,7之间是否连接? 否。8,9呢?是。
然后,我们执行连接命令:
union(5, 0)
union(7, 2)
union(1, 0)
union(6, 1)
那么现在0,7是否连接呢?是。
对于海量的数据:
这个算法适用场景? 比如
照片上的像素
- 网络上的节点
- 社交网络中的好友
- 电脑芯片中的晶体管
等等很多
代码实现:
package com.algorithms.week1;
//algorithm initialize union find
//quick-find N N 1
public class QuickFindUF {
// id数组的索引代表每个对象的名称,值代表连接情况:如果几个对象连接再在一起,则他们的数组值相同
private int[] id;
/**
* 初始化抽象的数据结构,为节点分配初始id.初始时,所有节点都没有关联
*
* set id of each object to itself (N array accesses)
*
* @param N
*/
public QuickFindUF(int N) {
id = new int[N];
for (int i = 0; i < N; i++)
id[i] = i;
}
/**
* check whether p and q are in the same component (2 array accesses)
*
* @param p
* @param q
* @return
*/
public boolean connected(int p, int q) {
return id[p] == id[q];
}
/**
* change all entries with id[p] to id[q] (at most 2N + 2 array accesses)
*
*
* In particular if you just have N union commands on N objects which is
* Unreasonable.
*
* n*n
*
* @param p
* @param q
*/
public void union(int p, int q) {
int pid = id[p];
int qid = id[q];
for (int i = 0; i < id.length; i++)
if (id[i] == pid)
id[i] = qid;
}
}
有个问题,这个 算法会很慢,因为对于union,如果有n个对象,其中每个对象与其他对象连接一次,则会有n*n次运算。这个在海量运算的场景中并不适用!怎么改进呢?待续。。。。