1. 程式人生 > 其它 >【Android開發】SeekBar

【Android開發】SeekBar

並查集

https://www.luogu.com.cn/problem/P3367

並查集問題非常經典,解法非常精妙

首先對每個元素做標號

資料結構就是一個數組,陣列中儲存的是對應根節點的標號

//初始化
for (int i=1;i<=k;i++) {
    f[i]=i;
}

所謂並查集,也就只有兩個操作,並和查

首先是查操作

int find(int k) {
    //如果根節點是自己,那麼返回
    if(f[k]==k)return k;
    //否則找父節點的根節點,並且做一下路徑壓縮,將父節點的根節點置為自己的根節點
    return f[k]=find(f[k]);
}

然後是並操作

void merge(int a, int b) {
    //把a的根節點掛到b的根節點上,如果只把a掛到b上,就無法顧及到a的根節點上的其他節點了
    f[find(a)]=find(b);
}

非常巧妙,短短几行程式碼,實現瞭如此複雜而又高效的邏輯

帶權並查集

無權的並查集應用範圍還是比較有限,加上權重,就能實現更復雜的邏輯,例如leetcode 399. 除法求值

帶上權重的話,就需要新增一個數組,儲存權重值,初始化為1

在這道題中,權重是商,那麼 w[i] 含義就是 N[i] = w[i] * N[f[i]]

for (int i=1;i<=k;i++) {
    f[i]=i;
    w[i]=1;
}

查操作和並操作

int find(int x) {
    if (f[x]==x) return x;
    int y=f[x];
    int z=find(y);
    //每進行一次find操作,w陣列也被更新過了,因此用更新過的y再更新x
    w[x]=w[x]*w[y];
    return f[x]=z;
}

void merge(int a, int b, double k) {
    int aa=find(a);
    int bb=find(b);
    f[aa]=bb;
    // a/b=k  a=w[a]*aa  b=w[b]*bb  w[aa]=aa/bb 推導可得 
    w[aa]=k*w[b]/w[a];
}