公交车最优换成次数计算

给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。

例如,路线 routes[0] = [1, 5, 7] 表示第 0 辆公交车会一直按序列 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> … 这样的车站路线行驶。
现在从 source 车站出发(初始时不在公交车上),要前往 target 车站。 期间仅可乘坐公交车。

求出 最少乘坐的公交车数量 。如果不可能到达终点车站,返回 -1 。

示例 1:
输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6 输出:2
解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。
示例 2:
输入:routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12 输出:-1

提示:
1 <= routes.length <= 500.
1 <= routes[i].length <= 105
routes[i] 中的所有值 互不相同
sum(routes[i].length) <= 105
0 <= routes[i][j] < 106
0 <= source, target < 106

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bus-routes

代码思路:
关于BFS就不细说了,不了解的可以自行百度,这道题可以从换成车辆做切入点,然后通过BFS筛选出最优换成次数

代码示例:

class Solution
{

    /**
     * @param Integer[][] $routes
     * @param Integer $S
     * @param Integer $T
     * @return Integer
     */
    function numBusesToDestination($routes, $S, $T)
    {

        if ($S == $T) {
            return 0;
        }
//入栈车号
        $queue = new SplQueue();
        $used  = [];
        foreach ($routes as $key => $route) {
            if (in_array($S, $route)) {
                $used[$key] = 1;
                $queue->enqueue($key);
            }
        }
        $site = 1;
        while (!$queue->isEmpty()) {
            $size = count($queue);
            for ($i = 0; $i < $size; $i++) {
                $top = $queue->dequeue();
                if (in_array($T, $routes[$top])) {
                    return $site;
                }
                foreach ($routes[$top] as $s) {
                    foreach ($routes as $key => $route) {
                        if (in_array($s, $route) && $used[$key] == 0) {
                            $used[$key] = 1;
                            $queue->enqueue($key);
                        }
                    }
                }
            }
            $site++;
        }

        return -1;
    }
}

$res = (new Solution)->numBusesToDestination([[1,2,7],[3,6,7]],1,6);

上面思路解题优化,遍历耗时比较严重,in_array函数滥用

class Solution
{

    /**
     * @param Integer[][] $routes
     * @param Integer $S
     * @param Integer $T
     * @return Integer
     */
    function numBusesToDestination($routes, $S, $T)
    {
        $len_r = count($routes);
        if ($S == $T) {
            return 0;
        }
        $newRoutes = [];
        foreach ($routes as $key => $route) {
            foreach ($route as $r) {
                $newRoutes[$key][$r] = 1;
            }
        }
        //var_dump($newRoutes);
//入栈车号
        $used  = [];
        $queue = new SplQueue();
        foreach ($newRoutes as $key => $route) {
            if (isset($newRoutes[$key][$T]) && isset($newRoutes[$key][$S])) {
                return 1;
            } elseif (isset($newRoutes[$key][$S])) {
                $queue->enqueue($key);
            }
        }
        $site = 1;
        while (!$queue->isEmpty()) {
            $size = count($queue);

            for ($i = 0; $i < $size; $i++) {
                $top = $queue->dequeue();
                if (isset($newRoutes[$top][$T])) {
                    return $site;
                }

                foreach ($routes[$top] as $s) {
                    foreach ($routes as $key => $route) {
                        if (isset($newRoutes[$key][$s]) && $used[$key] == 0) {
                            $used[$key] = 1;
                            $queue->enqueue($key);
                        }
                    }
                }
            }
            $site++;
        }

        return -1;
    }
}

$res = (new Solution)->numBusesToDestination([[1,2,7],[3,6,7]],1,6);

对应golang代码


package main

import (
    queue "container/list"
    "fmt"
)

func main()  {
    //[[],[],[],[],[],[],[],[],[4,5,8,9,24,44]]
    grid := [][]int{
        //{1,9,12,20,23,24,35,38,37},
        //{10,21,24,31,32,34,37,38,43},
        //{10,19,28,37},
        //{8},
        //{14,19},
        //{11,17,23,31,41,43,44},
        //{21,26,29,33},
        //{5,11,33,41},
        //{4,5,8,9,24,44},


        //{1,2,7},
        //{3,6,7},

        {3,16,33,45,59,79,103,135},
        {3,35,39,54,56,78,96,101,120,132,146,148},
        {37,70,107},
        {0,12,31,37,41,68,78,94,100,101,113,123},
        {11,32,52,85,135},
        {43,50,128},
        {15,19,34,37,45,52,56,97,108,123,142},
        {7,9,20,28,29,33,34,38,43,46,47,48,53,59,65,72,74,80,88,92,110,111,113,119,135,140},
        {15,41,64,83},
        {7,13,26,31,57,85,101,108,110,115,119,124,149},
        {47,61,67,70,74,75,77,84,92,101,124,132,133,142,147},
        {6,7,8,9,14,17,21,25,33,40,45,50,56,57,58,60,68,92,93,100,108,114,130,149},
        {5,16,22,48,77,82,108,114,124},
        {34,71},
        {8,16,32,48,104,108,116,134,145},
        {3,10,16,19,35,45,64,74,89,101,116,149},
        {1,5,7,10,11,18,40,45,50,51,52,54,55,69,71,81,82,83,85,89,96,100,114,115,124,134,138,148},
        {0,2,3,5,6,9,15,52,64,103,108,114,146},
        {5,33,39,40,44,45,66,67,68,69,84,102,106,115,120,128,133},
        {17,26,49,50,55,58,60,65,88,90,102,121,126,130,137,139,144},
        {7},
        {6,12,13,37,41,42,48,50,51,55,64,65,68,70,73,102,106,108,120,123,126,127,129,135,136,149},
        {6,7,12,33,37,41,47,53,54,80,107,121,126},
        {15,75,91,103,107,110,125,139,142,149},
        {18,24,30,52,61,64,75,79,85,95,100,103,105,111,128,129,142},
        {3,14,18,32,45,52,57,63,68,78,85,91,100,104,111,114,142},
        {4,7,11,20,21,31,32,33,48,61,62,65,66,73,80,92,93,97,99,108,112,116,136,139},
        {0,2,5,6,12,18,34,37,47,58,77,98,99,109,112,131,135,149},
        {0,13,49,51,53,55,60,65,66,80,82,87,92,99,112,118,120,125,128,131,137},




    }

    //res := numBusesToDestination(grid,37,28)
    //res := numBusesToDestination(grid,1,6)
    res := numBusesToDestination(grid,85,112)
    fmt.Println(res)
}

func numBusesToDestination(routes [][]int, source int, target int) int {
    if source ==target {
        return 0
    }
    carMap := make(map[int]map[int]int)
    for car,sites:=range routes{
        siteList := make(map[int]int)
        for _,site :=range sites{
            siteList[site] =1
        }
        carMap[car] = siteList

    }

    used := make(map[int]int)
    carQueue := queue.New()
    for car,route:= range carMap{
        if _,ok:=route[source];ok {
            used[car] = 1
            carQueue.PushBack(car)
        }
    }

    siteCount := 1
    for  carQueue.Len()!=0 {
        count :=carQueue.Len()
        for i:=0;i<count;i++ {
            car :=carQueue.Front()
            carQueue.Remove(car)
            carInt := car.Value.(int)
            if _,ok:=carMap[carInt][target];ok {
                return siteCount
            }
            for _,site := range routes[carInt] {
                for nextCar,siteList :=range carMap {
                    _,t := siteList[site]
                    if _, ok := used[nextCar];!ok && t  {
                        used[carInt] = 1
                        carQueue.PushBack(nextCar)
                    }
                }
            }
        }
        siteCount++
    }
    return -1
}

python3

class Solution:
    def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
        # 每个车站可以乘坐的公交车
        stations = defaultdict(set)
        for i, stops in enumerate(routes):
            for stop in stops:
                stations[stop].add(i)
        # 每个公交车线路可以到达的车站
        routes = [set(x) for x in routes]

        q = deque([(source, 0)])
        # 已经乘坐了的公交车
        buses = set()
        # 已经到达了的车站
        stops = {source}
        while q:
            pos, cost = q.popleft()
            if pos == target:
                return cost
            # 当前车站中尚未乘坐的公交车
            for bus in stations[pos] - buses:
                # 该公交车尚未到达过的车站
                for stop in routes[bus] - stops:
                    buses.add(bus)
                    stops.add(stop)
                    q.append((stop, cost + 1))
        return -1

(1) Comments

评论