【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)
}
相关推荐
Shea的笔记本37 分钟前
MindSpore实战笔记:Pix2Pix图像转换复现全记录
笔记·算法·机器学习·web3
清酒难咽40 分钟前
算法案例之蛮力法
c++·经验分享·算法
想逃离铁厂的老铁1 小时前
Day50 >> 98、可达路径 + 广度优先搜索理论基础
算法·深度优先·图论
散峰而望1 小时前
【数据结构】假如数据排排坐:顺序表的秩序世界
java·c语言·开发语言·数据结构·c++·算法·github
海棠AI实验室1 小时前
第十五章 字典与哈希:高效索引与去重
算法·哈希算法
独自破碎E1 小时前
动态规划-打家劫舍I-II
算法·动态规划
圣保罗的大教堂1 小时前
leetcode 3507. 移除最小数对使数组有序 I
leetcode
尽兴-1 小时前
JVM垃圾收集器与三色标记算法详解
java·jvm·算法·cms·gc·g1·三色标记算法
沐欣工作室_lvyiyi1 小时前
IIR数字带通滤波器(论文+源码)
算法·matlab·毕业设计·数字滤波器
zh_xuan1 小时前
LeeCode 61. 旋转链表
数据结构·c++·算法·leetcode·链表