1. 程式人生 > 實用技巧 >連線所有點的最小費用 - 最小生成樹Prim

連線所有點的最小費用 - 最小生成樹Prim

給你一個points陣列,表示 2D 平面上的一些點,其中points[i] = [xi, yi]。

連線點[xi, yi] 和點[xj, yj]的費用為它們之間的 曼哈頓距離:|xi - xj| + |yi - yj|,其中|val|表示val的絕對值。

請你返回將所有點連線的最小總費用。只有任意兩點之間 有且僅有一條簡單路徑時,才認為所有點都已連線。

剛開始寫出來的超出時間限制了:

class Solution {
    public int minCostConnectPoints(int[][] points) {
        if(points.length==1){
            
return 0; } int [][]cost=new int[points.length][points.length]; for(int i=0;i<points.length;i++){ for(int j=i;j<points.length;j++){ if(i==j){ cost[i][j]=Integer.MAX_VALUE; }else{ cost[i][j]
=Math.abs(points[i][0]-points[j][0])+Math.abs(points[i][1]-points[j][1]); cost[j][i]=cost[i][j]; } } } List<Integer> in=new ArrayList(); List<Integer> out=new ArrayList(); for(int i=0;i<points.length;i++){ out.add(i); } in.add(
0); out.remove(0); int i=1; int sum=0; while(in.size()<points.length){ sum=sum+helper(in,out,cost); } return sum; } public int helper(List<Integer> in,List<Integer> out,int [][]cost){ int min=Integer.MAX_VALUE; int minFlag=-1; for(Integer i:in){ for(Integer j:out){ if(cost[i][j]<min){ min=cost[i][j]; minFlag=j; } } } in.add(minFlag); out.remove(out.indexOf(minFlag)); return min; } }

看到一個優化,每次新增節點之後,更新一個ds[]是從未加入節點到樹的最小值,比如i,j都在裡面,k在外面,j是新加入的

那麼ds[k]=min{ds[k],cost[j][k]},而且加入的要用Set儲存,用list也會超出時間限制

class Solution {
    public int minCostConnectPoints(int[][] points) {
        if(points.length==1){
            return 0;
        }
        int [][]cost=new int[points.length][points.length];
        for(int i=0;i<points.length;i++){
            for(int j=i+1;j<points.length;j++){
                if(i==j){
                    cost[i][j]=Integer.MAX_VALUE;
                }else{
                    cost[i][j]=Math.abs(points[i][0]-points[j][0])+Math.abs(points[i][1]-points[j][1]);
                    cost[j][i]=cost[i][j];
                }
            }
        }
        Set<Integer> in=new HashSet();
        int []ds=new int[points.length];
        for(int i=0;i<points.length;i++){   
            ds[i]=cost[0][i];
        }
        in.add(0);
        
        int sum=0;
        for(int i=1;i<points.length;i++){
            int min=Integer.MAX_VALUE;
            int minF=-1;
            for(int j=0;j<points.length;j++){
                if(!in.contains(j)&&ds[j]<min){
                    min=ds[j];
                    minF=j;
                }
            }
            in.add(minF);
            sum=sum+min;
            for(int j=0;j<points.length;j++){
                if(cost[minF][j]<ds[j]){
                    ds[j]=cost[minF][j];
                }
            }
        }
        return sum;
    }
        
}