首页 > 编程语言 >java数据结构与算法刷题-----LeetCode134. 加油站

java数据结构与算法刷题-----LeetCode134. 加油站

时间:2024-03-19 16:00:14浏览次数:12  
标签:下标 java 油量 int gas 加油站 ----- LeetCode134 dp

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

在这里插入图片描述

1. 贪心

解题思路:时间复杂度O( n n n),空间复杂度O( 1 1 1)
  1. 暴力解法,从头到尾遍历加油站,以当前加油站为起点,判断是否可以行驶一周,时间复杂度为 O ( n 2 ) O(n^2) O(n2)
  2. 贪心思想,减小被检查加油站的数量,降低时间复杂度,只需遍历一遍数组
  3. 只要所有加油站的油量加起来 > 总耗油量,那就一定有一个加油站满足条件
  4. 但是,单纯的统计油量和花费汽油量,只能知道是否有个加油站满足条件,不能知道这个加油站是哪个
  5. 因此,我们需要在统计油量和花费汽油量的过程中,顺便找这个满足条件的加油站

贪心思路

  1. 从x出发,每经过一个加油站就加一次油(起始加油站也算),最多走到回到x为止,不多走
  2. 最后肯定会到达一个加油站,这个加油站有两种可能
  1. 回到了x,那么x就是满足条件的加油站
  2. 到达一个加油站Y,就走不下去了,无法回到x。
  1. 如果是第二种可能,到了Y,就走不下去了,无法完成绕一圈的操作。那么一个事实是:从x和y之间的任何一个加油站出发,都无法到达y的下一个加油站
  2. 那么很明显,贪心的思想就是,如果到y走不下去了,下次就从y+1走,同时我们需要重新统计油量和耗油量

代码思路

  1. 从0号加油站出发,每经过一个加油站(包括0号加油站)就统计可获得的油量总和sumOfGas,以及需要花费的油量总和sumOfCost
  2. 情况一:当走到y加油站时走不下去了(sumOfGas < sumOfCost),从y+1继续,同时sumOfGas 和sumOfCost归0,重新统计
  3. 情况二:正好绕了一圈,那么我们找到了这个加油站了
  4. 因为下标涉及循环,需要类似循环链表的循环下标法:下标 % 加油站数量 = 循环后的实际加油站位置。例如5个加油站,目前下标为9,那么我们在10%9 = 4号加油站,也就是最后一个加油站(下标从0开始);

时间复杂度,最多为2*n

  1. 最坏情况是,情况一,从0号加油站走到y后,走不下去了,此时从y+1继续走,依然走不下去。直到所有加油站都访问过时
  2. 此时发现所有加油站都走过了,则没有答案。因为无法完成绕一圈的操作时,从x和y之间的任何一个加油站出发,都无法到达y的下一个加油站。另外sumOfGas < sumOfCost也证明没有答案
代码

在这里插入图片描述

class Solution {
    //只要所有加油站的油量加起来 > 总耗油量,那就一定有一个加油站满足条件
    //所以,单纯的统计油量和花费汽油量,只能知道是否有这个加油站满足条件,不能知道这个加油站是哪个
    //因此,我们需要在统计油量和花费汽油量的过程中,顺便找这个满足条件的加油站
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int n = gas.length;
        int i = 0;//汽油下标
        while (i < n) {
            int sumOfGas = 0, sumOfCost = 0;//保存有多少汽油,和需要花费多少汽油。
            int cnt = 0;//当前车子走到哪里,注意这个是循环下标
            //此循环中,统计油量和花费汽油量
            while (cnt < n) {//cnt需要走一个循环
                int j = (i + cnt) % n;//获取循环下标(因为我们可以从最后一个加油站,直接回到第一个加油站)
                sumOfGas += gas[j];//每走到一个加油站,油量++,每个加油站只会累加一次
                sumOfCost += cost[j];//每离开一个加油站,油量花费++。每个花费只会累加一次
                if (sumOfCost > sumOfGas) {//如果花费,大于当前持有的油
                    break;//跳出,当前i号加油站不满足条件
                }
                cnt++;//否则继续行驶
            }
            if (cnt == n) {//如果cnt == n说明正好绕了一圈
                return i;//那么i是一个合适的起点
            } else {//否则内部循环遍历过的不用再次遍历
                //走到这里说明已经到达的加油站,都不满足条件,直接从下一个加油站继续
                i = i + cnt + 1;//从cnt当前所在加油站的下一个加油站继续走
            }
            //如果此时i>=n了,说明所有加油站都不合格,返回-1,否则继续循环
        }
        return -1;//如果最终无法到达,返回-1;
    }
}

2. 动态规划

解题思路:时间复杂度O( n n n),空间复杂度O( 1 1 1)
  1. dp[i]=dp[i-1]+gas[i]-cost[i],求最小的dp[i],并且最后dp[n-1]必须>0,不然无解
  2. gas = [1,2,3,4,5], cost = [3,4,5,1,2]为例:dp数组为 [-2,-4,-6,-3,0]。下标i代表从0号到i号加油站。保存的值是总油量(总获取油量 - 总消耗量)
  3. 如果最后一个元素为>=0,那么说明有解。但是哪个是起点加油站呢,只要找到dp数组中的最低点(最小值)的后一个即可
  4. 因为最低点,代表左边是下降曲线(消耗量>油量),右边一定是油量大于消耗量。所以最低点的右边,是第一个油量大于消耗量的,一定是起点。但是前提是dp数组最后一个元素>=0

按照上面的想法写代码,空间复杂度为O(n), 但是我们发现,我们每次计算i号加油站的dp值,只需要前一个i-1的状态,所以全部用一个变量即可操作。从而将空间复杂度降到O(1)

代码

在这里插入图片描述

class Solution {
    //动态规划 O(N)
    //dp[i] = dp[i-1] + gas[i] - cost[i],求最小的 dp[i],并且最后 dp[n-1] 必须 > 0,不然无解
    //gas = [1,2,3,4,5], cost = [3,4,5,1,2]
    //dp数组为 [-2,-4,-6,-3,0]。下标i代表从0号到i号加油站。保存的值是总油量(总获取油量 - 总消耗量)
    //如果最后一个元素为 >= 0,那么说明有解
    //但是哪个是起点加油站呢,只要找到dp数组中的最低点(最小值)的后一个即可
    //因为最低点,代表左边是下降曲线(消耗量>油量),右边一定是油量大于消耗量。所以最低点的右边,是第一个油量大于消耗量的,一定是起点
    int canCompleteCircuit(int[] gas, int[] cost) {
        int n = gas.length;
        // 相当于图像中的坐标点和最低点
        int sum = 0, minSum = 0;//sum即表示dp[i-1]又表示dp[i],minSum保存最低点的值
        int start = 0;//start保存最低点的下标
        for (int i = 0; i < n; i++) {
            sum += gas[i] - cost[i];//到这里,sum本身是dp[i-1],然后+=gas[i] - cost[i],变成dp[i]本身
            if (sum < minSum) {//如果sum是新的最低点
                // 经过第 i 个站点后,使 sum 到达新低
                // 所以站点 i + 1 就是最低点(起点)
                start = i + 1;
                minSum = sum;
            }
        }
        if (sum < 0) {//dp[n-1],也就是dp数组最后一个元素,小于0的话,就无解
            // 总油量小于总的消耗,无解
            return -1;
        }
        // 环形数组特性
        //如果sum,也就是dp[n - 1]>=0,说明有解,start就是起点,但是因为我们是循环数组,如果start是n,表示起点是0
        return start == n ? 0 : start;
    }
    
}

标签:下标,java,油量,int,gas,加油站,-----,LeetCode134,dp
From: https://blog.csdn.net/grd_java/article/details/136771150

相关文章

  • 基于Java中的SSM框架实现宝康药房销售管理系统项目【项目源码+论文说明】
    基于Java中的SSM框架实现宝康药房销售管理系统演示摘要随着我国市场经济的蓬勃发展和人们对医药产品需求的迅速增加,医药销售行业正处于一个高速发展的时期。行业的快速发展必然导致竞争的加剧,面对药品销售业日益严酷的竟争现实,加强管理、提高工作效率和改善服务质量成了急......
  • 23-有参转录组实战9-差异基因GO富集分析
    #这里需要对非模式物种制作ORG.DB包,如果是模式物种,“https://bioconductor.org/packages/release/BiocViews.html#___OrgDb”该网站有自带的成熟的包,自行下载使用就行。#对上一个教程中得到的out.emapper.annotations文件,对表头修整下:#windows上的R运行library(dplyr)libra......
  • 上海安川机器人SGM7G-30APK-YR11电机维修让你放心
    一、安川机器人SGM7G-30APK-YR11电机常见电机故障·绕组短路:电机长时间运行或过载可能导致绕组绝缘层损坏,进而引发短路。·轴承磨损:轴承是安川机器人SGM7G-30APK-YR11电机转动的关键部件,长时间使用或缺乏维护会导致磨损,影响电机精度和稳定性。·编码器故障:编码器用于提供......
  • 1948.Educational Codeforces Round 163 - sol
    202403补题效率低下。场上发挥并不是很好,A~E都是简单的,而场上没有去推F的式子,只是找了找规律,然后发现是一个不可做的东西就下播了。如果直接推式子就会很快地做出来,还是非常可惜。A.SpecialCharactersYouaregivenaninteger\(n\).Yourtaskistobuildast......
  • 安装docker-compose
    道客的安装路径已经不能用了!使用官方安装脚本自动安装安装命令如下:curl-fsSLhttps://get.docker.com|bash-sdocker--mirrorAliyun也可以使用国内daocloud一键安装命令:curl-sSLhttps://get.daocloud.io/docker|shUbuntuDocker安装DockerEngine-Community......
  • 五、jsPlumb实现流程图配置--连线
    一、线条创建在第一篇文章讲到过线条一共有四种类型Bezier、Straight、Flowchart、StateMachine,以及每种类型的样子,接下来就演示如何创建线条。创建一条连线有两种方式:通过代码创建;用户使用鼠标拖拽进行创建。1.通过代码创建使用jsPlumb提供的connectAPI可以创建连线。......
  • 摄像头组件2- 图像传感器
    目录概述1.公司背景介绍2.公司产品线介绍3.ARO233介绍4.特性5.实例参考链接概述    本文以安美森的AR0233为例,介绍"车载摄像头模组"子组件2-cmos图像传感器 1.公司背景介绍        公司:安森美半导体(ONSemiconductor)      ......
  • 没等来OpenAI,等来了Open-Sora全面开源
      ChatGPT狂飙160天,世界已经不是之前的样子。新建了人工智能中文站https://ai.weoknow.com每天给大家更新可用的国内可用chatGPT资源​ 发布在https://it.weoknow.com不久前OpenAISora以其惊人的视频生成效果迅速走红,在一众文生视频模型中突出重围,成为全球瞩目的焦......
  • 配置Flask-CLI以便与Flask应用程序一起使用
    第1步:创建Flask应用首先,你需要创建一个新的Flask应用(入口文件)。这可以通过创建一个包含Flask应用实例的Python文件来完成。创建一个名为 main.py 的文件,并在其中定义Flask应用。#main.pyfromflaskimportFlaskapp=Flask(__name__)@app.route('/')defindex():......
  • “源神”-马斯克,打脸OpenAI,如期开源Grok大模型
      ChatGPT狂飙160天,世界已经不是之前的样子。新建了人工智能中文站https://ai.weoknow.com每天给大家更新可用的国内可用chatGPT资源​ 发布在https://it.weoknow.com“源神”-马斯克就在刚刚,马斯克的xAI正式开源了Grok大模型的代码、权重和架构。该模型有3140亿参数,......