Interview Questions: Union–Find (ungraded)

最近在学coursera上的算法课程。下面是课后习题的答案。

1.

Social network connectivity. Given a social network containing nn members and a log file containing mm 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 \log nmlogn or better and use extra space proportional to nn.

Note: these interview questions are ungraded and purely for your own enrichment. To get a hint, submit a solution.

这题比较基础,有一个log file里面保存的数据是 时间  p  q,意思是在某个时刻p与q产生了联系,题目问在什么时候,所有人都产生了联系,即联通分量为1。

package sec1.Exercise;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Sec1Exercise {
    private int[] id;
    private int[] sz;
    private int count;
    FileInputStream ins;

    public Sec1Exercise(int N,FileInputStream ins){
        this.ins = ins;
        id = new int[N];
        sz = new int[N];
        count = N;
        for(int i = 0;i < N;i++){
            id[i] = i;
        }
        for(int i = 0;i < N;i++){
            sz[i] = 1;
        }


    }

    public String getEarlyTime(){
        Scanner scanner = new Scanner(ins,"utf-8");
        String time = null;
        while(scanner.hasNextLine()){
            String line = scanner.nextLine();
            if(line != null&&!line.trim().equals("")){
                String[] lineArray = line.split(" ");
                Integer p = Integer.parseInt(lineArray[1]);
                Integer q = Integer.parseInt(lineArray[2]);
                union(p,q);
                if (count == 1){
                    return lineArray[0];
                }
            }
        }
        return "";
    }

    public int find(int i){
        while(id[i] != i){
            i = id[i];
        }
        return i;
    }

    public void union(int i,int j){
        int pId = find(i);
        int qId = find(j);
        if(pId == qId){
            return;
        }
        if(sz[i] < sz[j]){
            sz[j] += sz[i];
            id[i] = j;
        }else{
            sz[i] += sz[j];
            id[j] = i;
        }
        count--;
    }

    public static void main(String[] args) {
        FileInputStream ins;
        try {
            ins = new FileInputStream("socialNetworkLog.txt");
            Sec1Exercise sec1Exercise = new Sec1Exercise(10,ins);
            System.out.println(sec1Exercise.getEarlyTime());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}


//socialNetworkLog.txt
//20170714001 0 1
//20170714002 4 5
//20170714003 8 9
//20170714004 2 4
//20170714005 5 6
//20170714006 7 8
//20170714007 2 5
//20170714008 6 7
//20170714009 1 2
//20170714010 0 3
//20170714011 1 9
//20170714012 3 7

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 ii. The operations, 𝚞𝚗𝚒𝚘𝚗(), 𝚌𝚘𝚗𝚗𝚎𝚌𝚝𝚎𝚍(), and 𝚏𝚒𝚗𝚍() should all take logarithmic time or better.

For example, if one of the connected components is \{1, 2, 6, 9\}{1,2,6,9}, then the 𝚏𝚒𝚗𝚍() method should return 99 for each of the four elements in the connected components.

这个题目的意思是求出每个联通分量中的最大值,若用quick-find法,则非常简单,每个联通分量的根节点即为最大值。若采用weighted-quick-union则需要维护一个max数组,每个联通分量的根节点保存最大值。

package sec1.Exercise;

public class UF {

    private int[] id;   //分量id
    private int[] sz;   //各个根节点所对应的分量的大小
    private int count;  //分量数量
    private int[] max;

    public UF(int N){
        count = N;
        id = new int[N];
        sz = new int[N];
        max = new int[N];
        for(int i = 0;i < N;i++){
            id[i] = i;
            sz[i] = 1;
            max[i] = i;
        }

    }

    public int count(){
        return count;
    }

    public boolean connected(int p,int q){
        return find(p) == find(q);
    }

    private int find(int i){
        while (id[i] != i){
            i = id[i];
        }
        return i;
    }

    public void union(int p,int q){
        int pId = find(p);
        int qId = find(q);

        if(pId == qId){
            return;
        }
        if(sz[pId] < sz[qId]){
            id[pId] = qId;
            sz[qId] += sz[pId];
            max[qId] = max[pId] > max[pId] ? max[pId] : max[qId];
        }else{
            id[qId] = pId;
            sz[pId] += sz[qId];
            max[pId] = max[pId] > max[qId] ? max[pId] : max [qId];
        }
        count--;
    }

    public int getMax(int i){
        return max[find(i)];
    }

}

3. 

Successor with delete. Given a set of nn integers S = \{ 0, 1, ... , n-1 \}S={0,1,...,n−1} and a sequence of requests of the following form:

  • Remove xx from SS
  • Find the successor of xx: the smallest yy in SS such that y \ge xy≥x.

design a data type so that all operations (except construction) take logarithmic time or better in the worst case

这个题目的意思是,有一段从0开始的连续序列,每次都会从序列中取出一个数x,求序列中比x大,但最小的那个数。

package sec1.Exercise;

public class Successor {

    private int N;
    private int[] num;
    private boolean[] isRemove;

    public Successor(int N){
        num = new int[N];
        for(int i = 0;i < N;i++){
            num[i] = i;
            isRemove[i] = false;
        }
    }

    public int find(int i){
        while(i != num[i]){
            i = num[i];
        }
        return i;
    }

    public void remove(int index){
        if(index - 1 >= 0&&isRemove[index - 1]){
            union(index,index - 1);
        }else if(index + 1 < N&&isRemove[index + 1]){
            union(index,index + 1);
        }
    }

    public void union(int p,int q){
        int i = find(p);
        int j = find(q);
        if(i == j){
            return;
        }
        if(i < j){
            num[i] = j;
        }else {
            num[j] = i;
        }
    }

    public int getSuccessor(int x){
        int num = find(x) + 1;
        if(num < N){
            return num;
        }
        return -1;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章