滑动窗口练习(三)— 加油站问题

news/2024/5/20 9:45:21 标签: 算法, 滑动窗口, java

题目
测试链接
在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gas 和 cost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

解释一下这道题,如下图所示:
路程数组gas和油耗数组cost,假设从A点出发,走到B点路程为1,消耗油量为2,1 - 2 = -1,油量不够支撑走到B点,所以如果从A点出发,无法完整的绕完一圈,B、C、D同理,这道题就是看从哪个出发点出发后,可以顺利的绕完一圈(gas和cost等长)。
在这里插入图片描述

滑动窗口
首先,先将给定的 gas[] 和 cost[] 稍稍加工一下,一次遍历,用gas[i] - cost[i],得到的新数组中包含正负数,就是从每个点出发的路程和油耗的差值,看是否有能力到达下一个目的地。

此时如果用暴力方法解这道题的话,只需要从0 ~ N - 1每个位置循环遍历,遍历N个位置。看过程中是否出现负数,如果是负数,则说明不能完成循环,如果不是,结果 >= 0,则证明可以完成循环。

我们这里直接说用滑动窗口的解题思路:
依然是先加工gas[] 和 cost[],不同的是,我们要根据加工出来的gas[] - cost[],搞出来一个2倍gas[]长度的前缀和数组

因为我们要看从 0 ~ N - 1位置中每个的出发点能否成功绕回来, gas[] - cost[] 加工出来的数组就是从每个点出发能否成功到达下一目的地的数组,所以当累加到N - 1位置时,下一步重新在加上 0 位置的值,来构造出这个2倍长度累加和数组。

这样的做的目的是,我下图中 double.length中下标4的位置,可以看做是从B点出发,又重新绕回A的0位置,下标5的位置,可以看做是从C点出发,重新绕回B点的1位置。一个数组全部可以搞定。

所有原始数组中出发的位置,在double.length中都可以将原始数组的累加和数组加工出来。
在这里插入图片描述

怎么加工?
假设我从D点出发,那么在gas - cost中求出来的累加和数组就是{3,2,2,4}(因为要重新往A点加绕回来),对应在double.length中就是划线部分,怎么得出来的呢?
划线数组中的每一个数,都减去划线部分的前一个数(1)。
在这里插入图片描述
所以,综上所述,此时我们维护一个窗口最小值,窗口范围就是gos.length,每次窗口变化后,根据窗口内最小值 - 前一个值,如果此时已然 < 0,则说明该位置不是最佳出发点。否则就认为是最佳出发点。

代码

java">   public static int canCompleteCircuit(int[] gas, int[] cost) {
        boolean[] booleans = goodArray(gas, cost);
        for (int i = 0; i < booleans.length; i++) {
            if (booleans[i]) {
                return i;
            }
        }
        return -1;
    }

    public static boolean[] goodArray(int[] gas, int[] cost) {
        int N = gas.length;
        int M = N << 1;

        int[] arr = new int[M];

        for (int i = 0; i < N; i++) {
            arr[i] = gas[i] - cost[i];
            arr[N + i] = gas[i] - cost[i];
        }

        for (int j = 1; j < M; j++) {
            arr[j] += arr[j - 1];
        }

        LinkedList<Integer> w = new LinkedList<>();

        for (int i = 0; i < N; i++) {
            while (!w.isEmpty() && arr[w.peekLast()] >= arr[i]) {
                w.pollLast();
            }
            w.addLast(i);
        }

        boolean[] ans = new boolean[N];
        for (int offset = 0, i = 0, j = N; j < M; offset = arr[i++], j++) {
            if (arr[w.peekFirst()] - offset >= 0) {
                ans[i] = true;
            }
            if (w.peekFirst() == i) {
                w.pollFirst();
            }
            while (!w.isEmpty() && arr[w.peekLast()] >= arr[j]) {
                w.pollLast();
            }
            w.addLast(j);
        }
        return ans;
    }

http://www.niftyadmin.cn/n/5251980.html

相关文章

资源三号卫星数字表面模型库

资源三号卫星数字表面模型库&#xff08;简称ChinaDSM-China Digital Surface Model&#xff09;是以资源三号卫星立体影像为数据源&#xff0c;采用自主知识产权的基于多基线、多匹配特征的地形信息自动提取技术&#xff0c;快速处理和生产提取的高精度、高保真15米格网数字表…

2022年拉丁美洲中东和非洲医疗机器人市场及全球概况报告

今天分享的是机器人系列深度研究报告&#xff1a;《2022年拉丁美洲中东和非洲医疗机器人市场及全球概况报告》。 &#xff08;报告出品方&#xff1a;Apollo Reports&#xff09; 报告共计&#xff1a;195页 研究方法论 2.1通过桌面研究和内部存储库的假设 a)最初&#xff…

基于YOLOv8的目标检测与计数

目录方法1&#xff1a; Jupyter Notebook方法2&#xff1a; 部署到Streamllit云的Streamlit Web应用 已知限制 方法3&#xff1a;在Streamlit中进行本地部署代码演示更多演示 目录 最近&#xff0c;我研究了Roboflow提供的名为Supervision的计算机视觉工具&#xff0c;重点关注…

Mybatis增删改查基础

MyBatis可根据查询的结果类型、查询条件的不同进行统一处理。 1 查询数据 1.1 根据查询数据条数来分析不同的情况 1.1.1 查询单条数据 可以通过实体类、list集合、map等处理查询结果。 通过实体类查询单条数据 User queryUserById(Param("id") Integer id);<…

Docker部署redis单节点

【百炼成魔】docker部署redis单节点 环境准备 关闭防火墙 systemctl stop firewalld && systemctl disable firewalldsetenforce 0 && sed -i s/SELINUX.*/SELINUXdisabled/g /etc/selinux/config安装常用软件 yum install -y wget net-tools bash-compl…

入门Redis学习总结

记录之前刚学习Redis 的笔记&#xff0c; 主要包括Redis的基本数据结构、Redis 发布订阅机制、Redis 事务、Redis 服务器相关及采用Spring Boot 集成Redis 实现增删改查基本功能 一&#xff1a;常用命令及数据结构 1.Redis 键(key) # 设置key和value 127.0.0.1:6379> set …

【C++】引用详解:引用的用法,注意事项,本质

目录 引用1.1 引用的基本使用1.2 引用注意事项1.3 引用做函数参数1.4 引用做函数返回值1.5 引用的本质1.6 常量引用 引用 1.1 引用的基本使用 作用&#xff1a; 给变量起别名 语法&#xff1a; 数据类型 &别名 原名 示例代码 #include<iostream> using namespace…

Python开发运维:Python垃圾回收机制

目录 一、理论 1.Python垃圾回收机制 一、理论 1.Python垃圾回收机制 &#xff08;1&#xff09;引⽤计数器 1&#xff09;环状双向链表 refchain 在python程序中创建的任何对象都会放在refchain链表中。 name "david" age 20 hobby ["篮球",游泳…