小v在公司负责游戏运营,今天收到一款申请新上架的游戏“跳一跳”,为了确保提供给广大玩家朋友们的游戏都是高品质的,按照运营流程小v必须对新游戏进行全方位了解体验和评估。这款游戏的规则如下:
有n个盒子排成了一行,每个盒子上面有一个数字a[i],表示在该盒子上的人最多能向右移动a[i]个盒子(比如当前所在盒子上的数字是3,则表示可以一次向右前进1个盒子,2个盒子或者3个盒子)。
现在小v从左边第一个盒子上开始体验游戏,请问最少需要移动几次能到最后一个盒子上?
有n个盒子排成了一行,每个盒子上面有一个数字a[i],表示在该盒子上的人最多能向右移动a[i]个盒子(比如当前所在盒子上的数字是3,则表示可以一次向右前进1个盒子,2个盒子或者3个盒子)。
输入 :2 2 3 0 4
表示现在有5个盒子,上面的数字分别是2, 2, 3, 0, 4。
输出:2
小v有两种跳法:
跳法1:盒子1 -> 盒子2 -> 盒子3 -> 盒子5,共3下
跳法2:盒子1 -> 盒子3 -> 盒子5,共2下
跳法2的步骤数最少,所以输出最少步数:2。
2 2 3 0 4
2
如果没有盒子或跳不到最后一个盒子上,则返回-1;如果已经在最后盒子上,则直接返回0。
''' Welcome to vivo ! ''' # leetcode 原题45 输出要改一下 #leetcode保证能跳到最后一个位置,这里不一定 def solution(step_list): n=len(step_list) max_num=0 cnt=0 end=0 for i in range(n-1): if i<=max_num: max_num=max(max_num,i+step_list[i]) #if max_num>=n-1 if i==end: end=max_num cnt=cnt+1 return cnt if max_num>=n-1 else -1 step_list = [int(i) for i in input().split()] print(solution(step_list))
private static int solution(int[] input) { if(input.length==1){ //如果只有一个盒子,那么起点即为终点,无需跳跃 return 0; } if(input.length>1&&input[0]==0){ //如果不只一个盒子,那么肯定需要跳动。但是起点位置能跳跃的距离为0 // 那么肯定到不了终点 return -1; } //下面的代码处理需要跳动才能到达终点的情况 int[] dp=new int[input.length]; for (int i=0;i<input.length;i++){ //计算能够到达最右的盒子 int range=Math.min(input.length-1,i+input[i]); for (int j=i+1;j<=range;j++){ if(dp[j]==0){ dp[j]=dp[i]+1; } } } int ret=dp[input.length-1]; //需要跳动的次数至少大于0,结果出现跳动0次,说明不可达,返回-1 return ret==0?-1:ret; }
def solution(step_list): # TODO Write your code here cur_pos = [0] # 刚开始在起点的0位置 n = len(step_list) if n == 1: return 0 steps = 0 while 1: next_pos = [] # pos下一步的临时位置 while cur_pos: pos = cur_pos.pop(0) if step_list[pos] == 0: # 此位置无法移动,直接跳过 continue # 否则遍历下一个位置的可能性 for step in range(1, step_list[pos] + 1): if pos + step >= n - 1: return steps + 1 else: # 如果跨step的下一个位置无法移动,则这一步不跳 if step_list[pos + step] == 0: continue next_pos.append(pos + step) if not next_pos: # 如果下一步全都无法移动,则直接break返回-1 break cur_pos = next_pos steps += 1 return -1 step_list = list(map(int, input().split())) print(solution(step_list))
#include <iostream> #include <stdlib.h> #include <string.h> #include <vector> #include <algorithm> #include <limits.h> using namespace std; bool flag; int solution(int a[], int N, int depth) { int min_depth = INT_MAX; if(N <= 0){ return depth; } if(a[0] == 0){ return -1; } for(int i = N-1; i >= 0; i--){ if(a[i]+i >= N){ int temp = solution(a,i,depth+1); min_depth = min(min_depth, temp); flag = true; } } if(flag){ return min_depth; }else{ return -1; } } int main() { string str(""); getline(cin, str); int a[2000]; int i = 0; char *p; int count = 0; const char* strs = str.c_str(); p = strtok((char *)strs, " "); while(p) { a[i] = atoi(p); count++; p = strtok(NULL, " "); i++; if(i >= 2000) break; } flag = false; int num = solution(a, count-1, 0); cout << num << endl; return 0; }AC版本答案,要注意一些特殊的情况,N=1或者,N=0,结果为0;a = [1,1]结果为1;a[0]为0的话,结果为-1,用一个flag值来判断能否跳到终点。
private static int rec(int[] input,int index){ if(index==input.length-1) return 0;//刚好到最后一格 if(index>input.length-1) return Integer.MAX_VALUE/2;//超出数组边界则返回一个较大的值 int steps = input[index];//索引处的步数 int step = Integer.MAX_VALUE/2;//设初始结果为不可能的较大值 for(int i=index+1;i<=index+steps;i++){ step = Math.min(step,rec(input,i));//从这个位置要到最后一个位置最少需要多少步 } return step+1;//返回步数,加上到达这个位置的一步 } private static int solution(int[] input) { // TODO Write your code here if(input.length==1) return 0; int step = rec(input,0);//从0开始递归 if(step<=input.length) return res;//步数不会大于数组的长度 return -1; }
//动态规划版本 private static int solution(int[] input) { if(input.length==1) return 0; int len = input.length; int[] steps = new int[len];//每个数组代表到最后位置的步数 Arrays.fill(steps,Integer.MAX_VALUE/2); steps[len-1]=0;//最后一个盒子是0 for(int i=len-2;i>=0;i--){//从后往前遍历 for(int j=1;j<=input[i];j++){//当前能走多少步 if(i+j>=len) break;//超过数组边界就没必要进行下去了 //计算当前位置到最后一个盒子需要多少步 steps[i]=Math.min(steps[i+j]+1,steps[i]); } } if(steps[0]<=len) return steps[0]; return -1; }
int solution(int a[], int N) { int left = 0; int right = 0; int step = 0; while (right < N - 1) { ++step; int next = right; for (int i = left; i <= right; ++i) { if (i + a[i] > next) { next = i + a[i]; left = i + 1; } } if (next == right) return -1; right = next; } return step; }
//i+a[i]即i位置最多可跳至i+a[i]位置,最后一个位置为N-1,假如我们想跳至位置j, //我们只需在j前面中找出不小于j的数就代表可跳至j,取最前面的那一个不小于j的就 //可得到最小步数。 int solution(int a[], int N) { // TODO Write your code here vector<int> v; for(int i = 0;i < N;i++){ v.push_back(i+a[i]); } if(v.size() == 1) return 0; int tmp = N-1; int step = 0; bool bark = false; for(int i = 0;i < tmp;i++){ if(v[i] >= tmp){ step++; if(i != 0){ tmp = i; i = -1; } else{ bark = true; break; } } } return (bark)?step:-1; }
//一大堆if else 的**算法 private static int solution(int[] input) { // TODO Write your code here if(input.length==1){ //如果只有一个盒子,那么起点即为终点,无需跳跃 return 0; } int step = 0; int end = input[0]; int big = input[0]; for(int i =0;i<input.length;i++){ if(end>=i){ if(big<input[i]+i){ big = input[i]+i; } }else if(end<i){ step++; end = big; if(end<i){ return -1; } big = input[i]+i; } if(end>=input.length-1){ step++; break; } } return step; }
def canJump(nums): steps = 0 max_Jump = 0 for i in range(len(nums)-1): if i > max_Jump: return -1 if max_Jump < i + nums[i]: steps +=1 max_Jump = i + nums[i] if max_Jump >= len(nums) - 1: return steps else: return -1 step_list = [int(i) for i in input().split()] print(canJump(step_list))case通过率100%
还是使用了递归的情况,把所有情况都考虑了一遍。后来想到,其实可以在times > min_times的时候就终止 此次递归。 void getResult(int a[], int start, int end,int times,int &min_times) { if (start < end && a[start] == 0) { return; // 不符合条件 } if (start >= end) { if (times < min_times) { // 更新最小值 min_times = times; } return; } for (int i = 1; i <= a[start]; i++) { getResult(a, start + i, end,times+1,min_times); // 迭代函数 } } int solution(int a[], int N) { int result = 0, min_times = N+1; // 设置不可能步数为初始值 getResult(a, 0, N - 1,result,min_times); if(min_times > N) return -1; return min_times; }
//递归(纯暴力) private static int solution(int[] input) { //len-1是终点,input[i]是在当前格子i,能够跳多远 int len=input.length; int ret=recursion(0,input[0],input, len);//从第0个格子开始起跳 return ret==len?-1:ret;//[0,1,0,1,1,0,0,0]永远跳不到终点 } //start是当前处在的位置 //capacity是当前格子能跳多远input[start] //len是数组input的长度 private static int recursion(int start,int capacity,int[] input,int len){ if(start==len-1){//到达终点 return 0;//从终点出发,需要多个步骤能到达目标,0步 } int ans=len; for(int i=1;i<=capacity;i++){ if(start+i<=len-1){//从当前格子跳出距离为i,不能超出终点 ans=Math.min(ans,1+recursion(start+i,input[start+i],input,len)); }else{ break;//憋跳了 } //选择不跳,可以等到下一次再跳,i++即可 } return ans; }