java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846  
 
 
 
 
 
 
  
贪心 解题思路:时间复杂度O( n n  n  1 1  1  
 
 暴力解法,从头到尾遍历加油站,以当前加油站为起点,判断是否可以行驶一周,时间复杂度为 O ( n 2 ) O(n^2)  O ( n 2 )  贪心思想,减小被检查加油站的数量,降低时间复杂度,只需遍历一遍数组 只要所有加油站的油量加起来 > 总耗油量,那就一定有一个加油站满足条件 但是,单纯的统计油量和花费汽油量,只能知道是否有个加油站满足条件,不能知道这个加油站是哪个 因此,我们需要在统计油量和花费汽油量的过程中,顺便找这个满足条件的加油站   
 贪心思路 
 从x出发,每经过一个加油站就加一次油(起始加油站也算),最多走到回到x为止,不多走 最后肯定会到达一个加油站,这个加油站有两种可能  回到了x,那么x就是满足条件的加油站 到达一个加油站Y,就走不下去了,无法回到x。   如果是第二种可能,到了Y,就走不下去了,无法完成绕一圈的操作。那么一个事实是:从x和y之间的任何一个加油站出发,都无法到达y的下一个加油站 那么很明显,贪心的思想就是,如果到y走不下去了,下次就从y+1走,同时我们需要重新统计油量和耗油量    
 代码思路 
 从0号加油站出发,每经过一个加油站(包括0号加油站)就统计可获得的油量总和sumOfGas,以及需要花费的油量总和sumOfCost 情况一:当走到y加油站时走不下去了(sumOfGas < sumOfCost),从y+1继续,同时sumOfGas 和sumOfCost归0,重新统计 情况二:正好绕了一圈,那么我们找到了这个加油站了 因为下标涉及循环,需要类似循环链表的循环下标法:下标 % 加油站数量 = 循环后的实际加油站位置。例如5个加油站,目前下标为9,那么我们在10%9 = 4号加油站,也就是最后一个加油站(下标从0开始);   
 时间复杂度,最多为2*n 
 最坏情况是,情况一,从0号加油站走到y后,走不下去了,此时从y+1继续走,依然走不下去。直到所有加油站都访问过时 此时发现所有加油站都走过了,则没有答案。因为无法完成绕一圈的操作时,从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)  { int  j =  ( i +  cnt)  %  n; sumOfGas +=  gas[ j] ; sumOfCost +=  cost[ j] ; if  ( sumOfCost >  sumOfGas)  { break ; } cnt++ ; } if  ( cnt ==  n)  { return  i; }  else  { i =  i +  cnt +  1 ; } } return  - 1 ; } 
} 
动态规划 解题思路:时间复杂度O( n n  n  1 1  1  
 
 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数组中的最低点(最小值)的后一个即可 因为最低点,代表左边是下降曲线(消耗量>油量),右边一定是油量大于消耗量。所以最低点的右边,是第一个油量大于消耗量的,一定是起点 。但是前提是dp数组最后一个元素>=0  
 按照上面的想法写代码,空间复杂度为O(n), 但是我们发现,我们每次计算i号加油站的dp值,只需要前一个i-1的状态,所以全部用一个变量即可操作。从而将空间复杂度降到O(1) 
 
  
 
 
 
  
class  Solution  { int  canCompleteCircuit ( int [ ]  gas,  int [ ]  cost)  { int  n =  gas. length; int  sum =  0 ,  minSum =  0 ; int  start =  0 ; for  ( int  i =  0 ;  i <  n;  i++ )  { sum +=  gas[ i]  -  cost[ i] ; if  ( sum <  minSum)  { start =  i +  1 ; minSum =  sum; } } if  ( sum <  0 )  { return  - 1 ; } return  start ==  n ?  0  :  start; } }