LeetCode 134. Gas Station
2016-05-27 12:17
267 查看
首先想到的方法是遍历每个节点,把每个节点当作出发点走一遍。设置剩余油量t,每走到一个节点判断是否能够走到下一个节点,即gas[i]+t>cost[i],来判断是否能够循环走一遍。若能则输出这个节点。
这种方法超时了。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int t;
for(int i=0;i<gas.size();i++)
{
t=0;
int flag=true;
int num;
for(int j=(i+1)%gas.size(),num=0;num!=gas.size()&&flag;j=(j+1)%gas.size(),num++)
{
int r=j-1?j-1:gas.size()-1;
if(t+gas[r]>=cost[r])
{
t=t+gas[r]-cost[r];
flag=true;
}
else
{
flag=false;
}
}
if(flag==true)
{
return i;
}
}
return -1;
}
};
以上算法超时,在这几基础上进行改进,我们设一个数组gp[]来记录每个站的加油量和即将走到下一站消耗油量的差值,若差值大于零,则表明从这个站点到下个站点是能存下多余的油,如果差值小于零,则表明从这个站点到下个站点要消耗从其他站点存下的油。
假设从i出发,到达j时,到达不了下个站点,即dp[i]+dp[i+1]+dp[i+2]+.....+dp[j-1]+dp[j]<0,因此车到达j点时剩余油量为大于等于零,j的站点的加油量要小于耗油量,因此不能把j点当作出发点,现在考虑j-1能不能作为出发站点呢,上式中车到j-1时,剩余油量有两种情况:大于零和等于零,若是大于零,这种情况下当车从j-1到达j时剩余油量不能满足车j到达j+1,因此不能做为出发点;等于零的时候,dp[i]+dp[i+1]+dp[i+2]+.....+dp[j-1]+dp[j]=dp[j-1]+dp[j]<0,因此也不能作为出发点。对于i到j的站点都能证明不能作为出发站点。
从j+1作为出发站点开始计算。如果计算的规模超过了站点的数量还没有找到出发点,说明没有站点符合条件,直接返回-1.
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
vector<int>gp(gas.size());
for(int i=0;i<gas.size();i++)
{
int t=0;
int num;
int j;
bool flag=true;
for(j=i,num=0;t>=0&&num!=gas.size();j=(j+1)%gas.size(),num++)
{
t+=gas[j]-cost[j];
if(j+1==gas.size())flag=false;
}
if(num==gas.size()&&t>=0)
{
return i;
}
else if(t<0&&flag==true)
{
i=j-1;
}
else if(flag==false)
{
return -1;
}
}
return -1;
}
};
看到网上还有一种解法,就是求最大连续子序列,最不容易理解的点是为什么最大连续子序列的的起始点就是我们要求的点,我是这么想的,首先要明确一点,最大连续子序列中从起点到终点,任意一点时dp的和都是正数,都是对总和是正向作用的。然后假设如果最大连续子序列的起点不是出发点,那么很容易得到其他点都不能作为出发点,因为最大的都不能抵消消耗的油。在求循环数组的最大连续子序列时,若是最大连续子序列横跨循环点时,此时可以求最小连续子序列,然后判断最大连续子序列和总和-最小连续子序列哪个大,这里运用的是:循环数组中最大连续子序列和最小连续子序列中的数集互为补集。
最后一个解法就不编码了。
这种方法超时了。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int t;
for(int i=0;i<gas.size();i++)
{
t=0;
int flag=true;
int num;
for(int j=(i+1)%gas.size(),num=0;num!=gas.size()&&flag;j=(j+1)%gas.size(),num++)
{
int r=j-1?j-1:gas.size()-1;
if(t+gas[r]>=cost[r])
{
t=t+gas[r]-cost[r];
flag=true;
}
else
{
flag=false;
}
}
if(flag==true)
{
return i;
}
}
return -1;
}
};
以上算法超时,在这几基础上进行改进,我们设一个数组gp[]来记录每个站的加油量和即将走到下一站消耗油量的差值,若差值大于零,则表明从这个站点到下个站点是能存下多余的油,如果差值小于零,则表明从这个站点到下个站点要消耗从其他站点存下的油。
假设从i出发,到达j时,到达不了下个站点,即dp[i]+dp[i+1]+dp[i+2]+.....+dp[j-1]+dp[j]<0,因此车到达j点时剩余油量为大于等于零,j的站点的加油量要小于耗油量,因此不能把j点当作出发点,现在考虑j-1能不能作为出发站点呢,上式中车到j-1时,剩余油量有两种情况:大于零和等于零,若是大于零,这种情况下当车从j-1到达j时剩余油量不能满足车j到达j+1,因此不能做为出发点;等于零的时候,dp[i]+dp[i+1]+dp[i+2]+.....+dp[j-1]+dp[j]=dp[j-1]+dp[j]<0,因此也不能作为出发点。对于i到j的站点都能证明不能作为出发站点。
从j+1作为出发站点开始计算。如果计算的规模超过了站点的数量还没有找到出发点,说明没有站点符合条件,直接返回-1.
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
vector<int>gp(gas.size());
for(int i=0;i<gas.size();i++)
{
int t=0;
int num;
int j;
bool flag=true;
for(j=i,num=0;t>=0&&num!=gas.size();j=(j+1)%gas.size(),num++)
{
t+=gas[j]-cost[j];
if(j+1==gas.size())flag=false;
}
if(num==gas.size()&&t>=0)
{
return i;
}
else if(t<0&&flag==true)
{
i=j-1;
}
else if(flag==false)
{
return -1;
}
}
return -1;
}
};
看到网上还有一种解法,就是求最大连续子序列,最不容易理解的点是为什么最大连续子序列的的起始点就是我们要求的点,我是这么想的,首先要明确一点,最大连续子序列中从起点到终点,任意一点时dp的和都是正数,都是对总和是正向作用的。然后假设如果最大连续子序列的起点不是出发点,那么很容易得到其他点都不能作为出发点,因为最大的都不能抵消消耗的油。在求循环数组的最大连续子序列时,若是最大连续子序列横跨循环点时,此时可以求最小连续子序列,然后判断最大连续子序列和总和-最小连续子序列哪个大,这里运用的是:循环数组中最大连续子序列和最小连续子序列中的数集互为补集。
最后一个解法就不编码了。
相关文章推荐
- 转弯
- 快速排序的几种优化
- CentOS [缺陷库管理工具JIRA]最新Linux版本jira6.3.6安装汉化破解以及数据迁移
- 中位数计数
- 黑色星期五
- 第二次冲刺阶段站立会议(四)
- [Effective JavaScript 笔记]第20条:使用call方法自定义接收者来调用方法
- Sprint总结
- JQ 点击指定文本框显示div。点击其他区域隐藏DIV
- java的反射机制(转)
- java.lang.NoSuchMethodError: antlr.collections.AST.getLine()I 与org.springframework.transaction
- 科学用百度,拒绝一切推广广告
- sqoop与mysql之间中文乱码
- 计算机组成原理 7
- 移动端touch事件封装
- UIScrollView UICollectionView 无法响应touch事件
- Thinkphp自定义代码生成工具及用法说明(附下载地址)
- 今天电信宽代终于装上光纤了,升级或安装光纤需购光猫,可以自购。我来扫盲一下
- mysql
- 94. Binary Tree Inorder Traversal