列表

详情


1334. 阈值距离内邻居最少的城市

n 个城市,按从 0n-1 编号。给你一个边数组 edges,其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold

返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市,则返回编号最大的城市。

注意,连接城市 ij 的路径的距离等于沿该路径的所有边的权重之和。

 

示例 1:

输入:n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4
输出:3
解释:城市分布图如上。
每个城市阈值距离 distanceThreshold = 4 内的邻居城市分别是:
城市 0 -> [城市 1, 城市 2] 
城市 1 -> [城市 0, 城市 2, 城市 3] 
城市 2 -> [城市 0, 城市 1, 城市 3] 
城市 3 -> [城市 1, 城市 2] 
城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市,但是我们必须返回城市 3,因为它的编号最大。

示例 2:

输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2
输出:0
解释:城市分布图如上。 
每个城市阈值距离 distanceThreshold = 2 内的邻居城市分别是:
城市 0 -> [城市 1] 
城市 1 -> [城市 0, 城市 4] 
城市 2 -> [城市 3, 城市 4] 
城市 3 -> [城市 2, 城市 4]
城市 4 -> [城市 1, 城市 2, 城市 3] 
城市 0 在阈值距离 2 以内只有 1 个邻居城市。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) { } };

rust 解法, 执行用时: 8 ms, 内存消耗: 2.5 MB, 提交时间: 2023-11-14 00:16:00

const INF:i32 = i32::max_value();
impl Solution {
    pub fn find_the_city(n: i32, edges: Vec<Vec<i32>>, distance_threshold: i32) -> i32 {
        let n = n as usize;
        let mut dis_table = vec![vec![INF;n];n];
        // init table
        for edge in edges {
            let city1 = edge[0] as usize;
            let city2 = edge[1] as usize;
            let dis = edge[2] as i32;
            dis_table[city1][city2] = dis;
            dis_table[city2][city1] = dis;
        }

        for city_index in 0..n {dis_table[city_index][city_index] = 0;}

        // Floyd
        for city_node in 0..n {
            for city_a in 0..n {
                for city_b in 0..n {
                    // from a to b by node
                    let dis_a:i32 = dis_table[city_node][city_a];
                    let dis_b:i32 = dis_table[city_node][city_b];
                    let dis_by_node = dis_a.saturating_add(dis_b);
                    if dis_table[city_a][city_b] > dis_by_node {
                        dis_table[city_a][city_b] = dis_by_node;
                        dis_table[city_b][city_a] = dis_by_node;
                    }
                }
            }
        }
        // Trust me, there`s no INF by now.

        // Stat Part
        let mut city_least_neighbor = n;
        let mut least_record = INF;
        for city in 0..n {
            let mut neighbor_count = 0;
            for dstn in 0..n {
                if dis_table[city][dstn] <= distance_threshold { neighbor_count+=1; }
            }
            if neighbor_count < least_record {
                city_least_neighbor = city;
                least_record = neighbor_count;
            } else if neighbor_count == least_record {
                if city > city_least_neighbor {city_least_neighbor = city;}
            } 
        }
        // return as i32
        city_least_neighbor as i32
    }
}

python3 解法, 执行用时: 348 ms, 内存消耗: 17.4 MB, 提交时间: 2023-10-24 07:49:26

import heapq

class Solution:
    def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int:
        dct = defaultdict(dict)
        for i, j, w in edges:
            dct[i][j] = w
            dct[j][i] = w

        ans = -1
        reach = n+1
        for i in range(n):
            cnt = set()
            stack = [[0, i]]
            while stack:
                dis, cur = heapq.heappop(stack)
                if dis > distanceThreshold:
                    break

                if cur in cnt:
                    continue
                cnt.add(cur)
                if len(cnt) > reach:
                    break

                for nex in dct[cur]:
                    if nex not in cnt:
                        heapq.heappush(stack, [dis+dct[cur][nex], nex])
                        
            if len(cnt) <= reach:
                ans = i
                reach = len(cnt)
        return ans

python3 解法, 执行用时: 568 ms, 内存消耗: 17.3 MB, 提交时间: 2023-10-24 07:48:59

class Solution:
    def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int:
        dis=[[float('inf') for _ in range(n)] for _ in range(n)]
        for i in range(n):dis[i][i]=0
        for i,j,w in edges:
            dis[i][j]=w
            dis[j][i]=w
        for k in range(n):
            for i in range(n):
                for j in range(n):
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j])
        res,count=0,n+1
        for i in range(n):
            cur=0
            for j in range(n):
                if dis[i][j]<=distanceThreshold:
                    cur+=1
            if cur<=count:
                res,count=i,cur
        return res

golang 解法, 执行用时: 16 ms, 内存消耗: 5.3 MB, 提交时间: 2023-10-24 07:48:38

func findTheCity(n int, edges [][]int, distanceThreshold int) int {
	// 定义邻接矩阵
	var dp [][]int
	for i := 0; i < n; i++ {
		var tmp []int
		for j := 0; j < n; j++ {
			if i == j {
				tmp = append(tmp, 0)
			} else {
				tmp = append(tmp, -1)
			}
		}
		dp = append(dp, tmp)
	}

	// 填出边长度
	for i := 0; i < len(edges); i++ {
		from := edges[i][0]
		to := edges[i][1]
		weight := edges[i][2]
		// 无向图
		dp[from][to] = weight
		dp[to][from] = weight
	}

	// dp转移方程
	// 将k放在第一层,后面的值依赖k
	for k := 0; k < n; k++ {
		for i := 0; i < n; i++ {
			for j := 0; j < n; j++ {
				// 相同节点跳过
				if i == j || j == k || i == k {
					continue
				}
				// 不通路也跳过
				if dp[i][k] == -1 || dp[k][j] == -1 {
					continue
				}
				tmp := dp[i][k] + dp[k][j]
				if dp[i][j] == -1 || dp[i][j] > tmp {
					dp[i][j] = tmp
					dp[j][i] = tmp
				}
			}
		}
	}
	min := n
	idx := 0
	for i := 0; i < n; i++ {
		cnt := 0
		for j := 0; j < n; j++ {
			if i == j {
				continue
			}
			if dp[i][j] <= distanceThreshold {
				cnt++
			}
		}
		if cnt <= min {
			min = cnt
			idx = i
		}
	}
	return idx
}

golang 解法, 执行用时: 24 ms, 内存消耗: 6.8 MB, 提交时间: 2023-10-24 07:48:25

const inf = 0x3f3f3f3f

type edge struct {
	x    int
	time int
} // 定义边结构体,字段为到to节点,和到to的时间

// go 语言中,不提供有限队列数据结构,需要结合heap自己实现
type hp []edge

func (h hp) Len() int              { return len(h) }
func (h hp) Less(i, j int) bool    { return h[i].time < h[j].time }
func (h hp) Swap(i, j int)         { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v interface{})   { *h = append(*h, v.(edge)) }
func (h *hp) Pop() (v interface{}) { a := *h; *h, v = a[:len(a)-1], a[len(a)-1]; return }

func dijkstraStart(graphs [][]edge, n int, start int) []int {
	dist := make([]int, n)

	for i := 0; i < n; i++ {
		dist[i] = inf
	}

	h := &hp{}
	heap.Init(h)

	heap.Push(h, edge{x: start, time: 0})
	dist[start] = 0

	for h.Len() > 0 {
		node := heap.Pop(h).(edge)
		cur, curdist := node.x, node.time

		if dist[cur] < curdist { // 0 肯定不可能大于 d,所以第一次一定不走这个
			continue
		}

		for _, nextNode := range graphs[cur] {
			next, nextdist := nextNode.x, nextNode.time

			if nextdist+dist[cur] < dist[next] {
				dist[next] = nextdist + dist[cur]
				heap.Push(h, edge{x: next, time: dist[next]})
			}
		}
	}

	return dist
}

func findTheCity(n int, edges [][]int, distanceThreshold int) int {
	graph := make([][]edge, n)
	for _, ev := range edges {
		graph[ev[0]] = append(graph[ev[0]], edge{x: ev[1], time: ev[2]})
		graph[ev[1]] = append(graph[ev[1]], edge{x: ev[0], time: ev[2]})
	}

	toCityMax := math.MaxInt32
    cityIdx := -1

	for i := 0; i < n; i++ {
		dist := dijkstraStart(graph, n, i)

		count := 0
		for _, dv := range dist {
			if dv > 0 && dv <= distanceThreshold {
				count++
			}
		}

        if toCityMax >= count {
            toCityMax = count
            cityIdx = i
        }
	}

	return cityIdx
}

java 解法, 执行用时: 17 ms, 内存消耗: 41.9 MB, 提交时间: 2023-10-24 07:47:47

class Solution {
    // dijkstra
    public int findTheCity(int n, int[][] edges, int distanceThreshold) {
        int[][] map = new int[n][n];
        final int INF = 0x3f3f3f3f;
        //init map
        for (int[] ints : map) {
            Arrays.fill(ints, INF);
        }
        for (int i = 0; i < n; i++) {
            map[i][i] = 0;
        }
        for (int[] e : edges) {
            map[e[0]][e[1]] = map[e[1]][e[0]] = e[2];
        }
        int res = 0;
        int MIN = n + 1;

        for (int i = 0; i < n; i++) {
            int[] dist = new int[n];
            boolean[] set = new boolean[n];
            for (int v = 0; v < n; v++) {
                dist[v] = map[i][v];
            }
            dist[i] = 0;
            set[i] = true;
            for (int j = 0; j < n - 1; j++) {
                int min = INF;
                int start = i;
                for (int k = 0; k < n; k++) {
                    if (!set[k] && dist[k] < min) {
                        min = dist[k];
                        start = k;
                       }
                }
                set[start] = true;
                for (int k = 0; k < n; k++) {
                    if (!set[k] && dist[k] > dist[start] + map[start][k]) {
                        dist[k] = dist[start] + map[start][k];
                    }
                }
            }
            int temp = 0;
            for (int j = 0; j < dist.length; j++) {
                if (dist[j] <= distanceThreshold) {
                    temp++;
                }
            }
            if (temp <= MIN) {
                MIN = temp;
                res = i;
            }
        }
        return res;
    }

    // floyd
    public static int findTheCity2(int n, int[][] edges, int distanceThreshold) {
        int[][] map = new int[n][n];

        //init
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j) {
                    map[i][j] = 0;
                } else {
                    map[i][j] = Integer.MAX_VALUE;
                }
            }
        }
        //get map 
        for (int[] e : edges) {
            map[e[0]][e[1]] = map[e[1]][e[0]] = e[2];
        }
        for (int k = 0; k < n; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (i != k && j != k && map[i][k] != Integer.MAX_VALUE && map[k][j] != Integer.MAX_VALUE) {
                        map[i][j] = Math.min(map[i][j], map[i][k] + map[k][j]);
                    }
                }
            }
        }

        //get res
        int min = n + 1;
        int res = -1;
        for (int i = 0; i < n; i++) {
            int count = 0;
            for (int j = 0; j < n; j++) {
                if (i != j && map[i][j] <= distanceThreshold) {
                    count++;
                }
            }
            if (min >= count) {
                min = count;
                res = i;
            }
        }
        return res;
    }
}

javascript 解法, 执行用时: 68 ms, 内存消耗: 43 MB, 提交时间: 2023-10-24 07:46:24

/**
 * @param {number} n
 * @param {number[][]} edges
 * @param {number} distanceThreshold
 * @return {number}
 */
const findTheCity = (n, edges, distanceThreshold) => {
  const MAX = 10001;
  const distance = Array.from({ length: n }, () => new Uint16Array(n).fill(MAX));
  for (const edge of edges) {
    distance[edge[0]][edge[1]] = distance[edge[1]][edge[0]] = edge[2];
  }
  for (let i = 0; i < n; ++i) {
    for (let j = 0; j < n; ++j) {
      if (i === j || distance[j][i] === MAX) continue;
      for (let k = j + 1; k < n; ++k) {
        distance[k][j] = distance[j][k] = Math.min(distance[j][k], distance[j][i] + distance[i][k]);
      }
    }
  }

  let city = 0;
  let minNum = n;
  for (let i = 0; i < n; ++i) {
    let curNum = 0;
    for (let j = 0; j < n; ++j) {
      distance[i][j] <= distanceThreshold && ++curNum;
    }
    if (curNum <= minNum) { minNum = curNum; city = i; }
  }
  return city;
};

cpp 解法, 执行用时: 36 ms, 内存消耗: 11.6 MB, 提交时间: 2023-10-24 07:45:07

class Solution {
public:
    void dijkstra(int graph[101][101], int dist[101], int v, int n) {
        // 初始化 dist
        for (int i = 0; i < n;  i++) {
            dist[i] = graph[v][i];
        }
        // 标记当前点是否已经加入集合
        bool m[101];
        memset(m, 0, sizeof(m));
        m[v] = true;

        // 每次都找离集合最近的一个点,一共要找 n-1 次
        for (int k = 0; k < n-1; k ++) {
            int minv = INT_MAX;
            int next = v;
            for (int i = 0; i < n; i ++) {
                if (!m[i] && dist[i] < minv) {
                    minv = dist[i];
                    next = i;
                }
            }
            m[next] = true;
            // 每次找到最近的点,并用它更新其它点到集合的距离,
            // 也就是更新dist数组
            for (int i = 0; i < n; i ++) {
                if (m[i] || graph[next][i] == INT_MAX) {
                    continue;
                }
                dist[i] = min(dist[i], dist[next] + graph[next][i]);
            }
        }
    }

    int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {
        // 定义并初始化邻接矩阵 graph
        int graph[101][101];
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < n; j ++) {
                graph[i][j] = INT_MAX;
            }
        }
        for (auto& edge : edges) {
            graph[edge[0]][edge[1]] = edge[2];
            graph[edge[1]][edge[0]] = edge[2];
        }

        int mincnt = INT_MAX;
        int ret = 0;
        for (int i = 0; i < n; i ++) {
            // 使用单源最短路径dijkstra算法生成:
            // 以i为源点到其它各点的最短路径数组dist
            int dist[101];
            dijkstra(graph, dist, i, n);
            
            int cnt = 0;
            for (int j = 0; j < n; j ++) {
                if (dist[j] <= distanceThreshold) {
                    cnt ++;
                }
            }
            if (cnt <= mincnt) {
                mincnt = cnt;
                ret = i;
            }
        }
        return ret;
    }
};

cpp 解法, 执行用时: 84 ms, 内存消耗: 12 MB, 提交时间: 2023-10-24 07:44:45

class Solution {
public:
    // floyd 算法 d[i][j], 表示i到j的距离
    int findTheCity(int n, vector <vector<int>> &edges, int distanceThreshold) {
        // 定义邻接矩阵D,并初始化各个城市间距离为INT_MAX(无穷)
        vector <vector<int>> D(n, vector<int>(n, INT_MAX));
        // 根据edges[][]初始化D[][]
        for (auto &e : edges) {
            // 无向图两个城市间的两个方向距离相同
            D[e[0]][e[1]] = e[2];
            D[e[1]][e[0]] = e[2];
        }
        // Floyd算法
        for (int k = 0; k < n; k++) {
            // n个顶点依次作为插入点
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (i == j || D[i][k] == INT_MAX || D[k][j] == INT_MAX) {
                        // 这些情况都不符合下一行的if条件,
                        // 单独拿出来只是为了防止两个INT_MAX相加导致溢出
                        continue;
                    }
                    D[i][j] = min(D[i][k] + D[k][j], D[i][j]);
                }
            }
        }
        // 选择出能到达其它城市最少的城市ret
        int ret;
        int minNum = INT_MAX;
        for (int i = 0; i < n; i++) {
            int cnt = 0;
            for (int j = 0; j < n; j++) {
                if (i != j && D[i][j] <= distanceThreshold) {
                    cnt++;
                }
            }
            if (cnt <= minNum) {
                minNum = cnt;
                ret = i;
            }
        }
        return ret;
    }
};

上一题