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;
    }

}

 

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