【LeetCode】【每日一题】1184. 公交站间的距离

LeetCode 1184. 公交站间的距离

题目描述详见LeetCode原题目。

这道题的题目可以抽象成,给定一个环,环上有若干个结点,它们彼此相继连接,形成一个环形图。结点有距离,保存在数组 a a a当中, a = [ 1 , 2 , 3 , 4 ] a=[1, 2, 3, 4] a=[1,2,3,4]表示的是结点 a 1 → a 2 a_1 \rightarrow a_2 a1→a2之间的距离为 1 1 1, a 2 → a 3 a_2 \rightarrow a_3 a2→a3之间的距离为 2 2 2, a 3 → a 4 a_3 \rightarrow a_4 a3→a4之间的距离为 3 3 3, a 4 → a 1 a_4 \rightarrow a_1 a4→a1之间的距离为 4 4 4。注意图的连接关系是双向的,即从某个结点可以向前走也可以向后走。

现在给定一个query,它有start和destination组成,二者均对应于环形图当中的结点编号,求从 s t a r t → d e s t i n a t i o n start \rightarrow destination start→destination之间的最短距离,也就是双向距离当中的最小者。

给出这道题之后我的思路是非常明确的,先后求从 s t a r t → d e s t i n a t i o n start \rightarrow destination start→destination向前走和向后走的最短距离即可,但是在实现上遇到了坑。

参考了LeetCode C++部分的题解,豁然开朗,其中利用到了C++ numeric库当中的accumulate,我感觉非常的使用,便在此进行记录。

accumulate有四个参数,分别是迭代器的起始位置、终点位置、累加的初始值以及自定义操作函数,前三个参数是必须的,第四个由于还没有用到所以不做深究。

在最开始,如果 s t a r t start start的位置在 d e s t i n a t i o n destination destination的右侧,那么可以交换二者的位置,使得 s t a r t start start永远比 d e s t i n a t i o n destination destination小,有助于后续的问题分析,二者是等价的。

现在,答案是显而易见的,由两部分当中的较小者组成,第一部分是从 s t a r t start start直接"向右"走到 d e s t i n a t i o n destination destination的距离,而第二部分是从 s t a r t start start向相反方向(此时一定经过了编号为0的结点)走到 d e s t i n a t i o n destination destination的距离。分别对应于accumulate(distance.begin() + start, distance.begin() + destination, 0)accumulate(distance.begin(), distance.begin() + start, 0) + accumulate(distance.begin() + destination, distance.end(), 0)

经过我自己的实验发现,accumulate当中迭代器的位置也是左闭右开的,意味着第二个参数"迭代器的终点"将不会被累加,累加一直持续到"迭代器终点的前一个位置" 。这与vector容器的begin(), end()也是左闭右开是对应的,因此使用accumulate(v.begin(), v.end(), 0)可以完成对vector对象v当中元素的累加。

本题最关键的一点也就是要意识到给定的distance数组是左开右闭的,需要利用这一点来进行累加。

本题的代码实现如下:

cpp 复制代码
class Solution {
public:
    int distanceBetweenBusStops(vector<int>& distance, int start, int destination) {
        if(start > destination) {
            swap(start, destination);
        }
        cout << accumulate(distance.begin()+start, distance.begin()+destination, 0) << endl;
        cout << accumulate(distance.begin(), distance.begin()+start, 0) + 
            accumulate(distance.begin()+destination, distance.end(), 0) << endl;
        return min(
            accumulate(distance.begin()+start, distance.begin()+destination, 0),
            accumulate(distance.begin(), distance.begin()+start, 0) + 
            accumulate(distance.begin()+destination, distance.end(), 0)
        );
    }
};

Go语言对应的实现,Go语言的实现中没有用到累加函数,而是直接使用for循环进行累加,注意处理左开右闭这条性质即可:

go 复制代码
func distanceBetweenBusStops(distance []int, start int, destination int) int {
    if start > destination { 
        start, destination = destination, start // 注意start和destination是参数, 它们已经被声明了
        // 此处不能够使用 := 进行swap, 而应该直接使用 =
    }

    ans_1, ans_2 := 0, 0
    
    for i:=0; i<len(distance); i++ {
        if start <= i && i < destination { // 处理左开右闭, 计算的是从start正向走到destination的距离
            ans_1 += distance[i]
        } else {						   // 从start反向走到destination的距离
            ans_2 += distance[i]
        }
    }

    return min(ans_1, ans_2)
}
相关推荐
程序猿进阶1 小时前
如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?
java·ide·vscode·算法·面试·职场和发展·架构
Eloudy1 小时前
一个编写最快,运行很慢的 cuda gemm kernel, 占位 kernel
算法
程序猿练习生1 小时前
C++速通LeetCode中等第5题-无重复字符的最长字串
开发语言·c++·leetcode
king_machine design2 小时前
matlab中如何进行强制类型转换
数据结构·算法·matlab
西北大程序猿2 小时前
C++ (进阶) ─── 多态
算法
无名之逆2 小时前
云原生(Cloud Native)
开发语言·c++·算法·云原生·面试·职场和发展·大学期末
头发尚存的猿小二2 小时前
树——数据结构
数据结构·算法
好蛊2 小时前
第 2 课 春晓——cout 语句
c++·算法
山顶夕景2 小时前
【Leetcode152】分割回文串(回溯 | 递归)
算法·深度优先·回溯
紫钺-高山仰止3 小时前
【Matlab】matlab 结构体使用方法
数据结构·算法·matlab