【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)
}
相关推荐
刚学HTML1 小时前
leetcode 05 回文字符串
算法·leetcode
AC使者1 小时前
#B1630. 数字走向4
算法
冠位观测者1 小时前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
古希腊掌管学习的神2 小时前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca2 小时前
洛谷 P1706 全排列问题 C语言
算法
古希腊掌管学习的神2 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
浊酒南街2 小时前
决策树(理论知识1)
算法·决策树·机器学习
就爱学编程2 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
Schwertlilien3 小时前
图像处理-Ch4-频率域处理
算法