Interview Questions
Social network connectivity
题目描述
Given a social network containing n
members and a log file containing m
timestamps at which times pairs of members formed friendships, design an algorithm to determine the earliest time at which all members are connected (i.e., every member is a friend of a friend of a friend ... of a friend). Assume that the log file is sorted by timestamp and that friendship is an equivalence relation. The running time of your algorithm should be m logn
or better and use extra space proportional to n
.
解答
题目提炼:n 个对象 m 条 union 记录(每次 2 个对象建立连接),找到第几次 union 后所有对象全连接。
数据结构:
- 一个容量为 n 的数组,初始状态存储各自 index;
- 一个容量为 n 的数组,记录树的对象数量;
- 一个常量记录树的数量,当数量为 1 的时候全部对象互相连接;
- 私有方法 root,获得某个对象的 root;
- 公有方法 union,连接两个对象,修改 root,如果树的数量降低为 1 返回 true,否则为 false。
/**
*array id stores root of each object;
*array size stores the number of objects of each tree;
*constant component represents the number of trees;
*function root returns the root of the specific object;
*function union recalculate the root of one object and the number of trees, *when the number decreases to one, it returns true, vice versa.
*/
public class SocialNetwork {
private int[] id;
private int[] size;
private int component;
public SocialNetwork(int n) {
component = n;
id = new int[n];
for (int i = 0; i < n; i++) {
id[i] = i;
}
}
private int root(int i) {
int count = 0;
while (i != id[i]) {
i = id[i];
count += 1;
}
size[i] = count;
return i;
}
public boolean union(int p, int q) {
int rootP = root(p);
int rootQ = root(q);
if (rootP != rootQ) {
component -= 1;
if (component == 1) { return true; }
if (size[p] >= size[q]) {
id[q] = rootP;
} else {
id[p] = rootQ;
}
}
return false;
}
}
Union-find with specific canonical element
题目描述
Add a method () to the union-find data type so that () returns the largest element in the connected component containing i
. The operations, (), (), and () should all take logarithmic time or better.
For example, if one of the connected components is {1,2,6,9}, then the () method should return 9 for each of the four elements in the connected components.
解答
在平衡树的前提下,增加一个方法 find(int p)
返回 p
所在 components 中最大的元素。
过去查找 root 的搜索是向上搜索寻找树的根,find 的不同是要双向搜索检索最大的元素。但是双向搜索无法满足 logN 的算法复杂度,所以必须在 union 的时候处理每棵树的最大值问题,增加一个 max 的数组记录每棵树的最大元素。
public class FindUF {
private int[] id;
private int[] size;
private int[] max;
public FindUF(int n) {
id = new int[n];
for (int i = 0; i < n; i++) {
id[i] = i;
}
}
private int root(int i) {
int count = 0;
int max = i;
List candidates = new ArrayList();
candidates.add(i);
while (i != id[i]) {
i = id[i];
count += 1;
max = i > max : i ? max;
candidates.add(i);
}
size[i] = count;
max[i] = max;
for (candidate : candidates) {
max[candidate] = max;
}
return i;
}
public void union(int p, int q) {
int rootP = root(p);
int rootQ = root(q);
if (rootP != rootQ) {
if (size[p] >= size[q]) {
id[q] = rootP;
} else {
id[p] = rootQ;
}
}
}
public boolean connected(int p, int q) {
return root(p) == root(q);
}
public int find(int i) {
return max[i];
}
}
Successor with delete
题目描述
Given a set of n integers S = { 0, 1, ... , n-1 } and a sequence of requests of the following form:
Remove x from S
Find the successor of x: the smallest y in S such that y≥x.
design a data type so that all operations (except construction) take logarithmic time or better in the worst case.
解答
输入一组整数,从中删除一个数,找到这个数后续比他大的最小的数字。
从这个数字的位置开始向后遍历,如果数字比删除数字大,则和当前最小数比较,如果比当前最小数小,则更新最小数字,直到结束,返回最小数字即可。
public class SuccessorDelete {
private int[] sequence;
public SuccessorDelete(int[] intArray) {
sequence = intArray;
}
public int delete(int p) {
int min;
boolean start = false;
for (int i = 0; i < sequence.length(); i ++) {
if (!start && p != sequence[i]) { continue; }
if (!start) { start = true; }
if (start) {
if (sequence[i] >= p) {
if (min == null) { min = sequence[i]; }
else { min = sequence[i] < min ? sequence[i] : min; }
}
}
}
return min;
}
}