403. Frog Jump

1定义

名称

意义

i

石块在数组stones中的下标

position[i]

第i个石块的position,即stones[i]

max_last_step[i]

到达第i个石块的最后一步所有可能的步长的最大值

 

 

 

2初始状态分析

由于position =1的下一跳position只能是2,3, 因此若可达,两者必有一个有石块,因此初始状态为以下三个状态之一:

(1) 若position = 2, position = 3都有石块,则状态为:

i123
position[i]123
max_last_step[i]112


(2) 若position = 2有石块,position =3没有石块,则状态为:

i12
position[i]12
max_last_step[i]11


 

(3) 若position = 2没有石块,position =3有石块,则状态为:

i12
position[i]13
max_last_step[i]12


 

 

3三个推论



4算法描述

广度优先遍历每个石块。

使用一个二维数组visited记录遍历到的每个石块在数组stones中的下标和上一跳的步长。由推论一,这个二维数组的每个维度的长度都不超过stones数组的长度。

 

5优化

由推论三,若最后一个石块可达,则stones数组必须满足:

因此,可以先对stones数组遍历一遍,判断该必要条件是否满足。

 

 

6算法实现

具体实现中,为了减少减法运算,把二维数组visited中的上一跳步长改为了下一跳最小步长,即上一跳步长-1

 

 



#include <stdbool.h>
#include <stdlib.h>

struct record {
	int stone_index;
	int min_step;
};

bool binary_search(int *arr, int size, int elem, int *index)
{
	int start = 2;
	int end = size - 1;
	int mid;

	while (start <= end)
	{
		mid = (start + end) >> 1;

		if (elem == arr[mid])
		{
			*index = mid;
			return true;
		}

		if (elem < arr[mid]) end = mid - 1;
		else start = mid + 1;
	}

	*index = start;
	return false;
}

bool can_cross(int* stones, int stonesSize, int **visited, struct record *queue)
{
	int last_stone = stones[stonesSize - 1];
	struct record *curr;
	int front = 0;
	int tail = 0;
	int stone_position;
	int stone_index;
	bool is_stone;
	int curr_min_step;

	curr = &queue[tail++];
	curr->stone_index = 1;
	curr->min_step = 0;
	visited[1][0] = 1;

	while (front != tail)
	{
		curr = &queue[front++];

		curr_min_step = curr->min_step;
		stone_position = stones[curr->stone_index] + curr_min_step;
		curr_min_step--;

		if (stone_position == last_stone || stone_position + 1 == last_stone ||
			stone_position + 2 == last_stone) return true;

		is_stone = binary_search(stones, stonesSize, stone_position, &stone_index);

		if(is_stone && curr_min_step >= 0 && !visited[stone_index][curr_min_step])
		{
			curr = &queue[tail++];
			curr->stone_index = stone_index;
			curr->min_step = curr_min_step;
			visited[stone_index][curr_min_step] = 1;
		}

		stone_position++;
		curr_min_step++;

		if (stone_index < stonesSize && stones[stone_index] < stone_position)
		{
			stone_index++;
		}

		if (stone_index < stonesSize && stones[stone_index] == stone_position && !visited[stone_index][curr_min_step])
		{
			curr = &queue[tail++];
			curr->stone_index = stone_index;
			curr->min_step = curr_min_step;
			visited[stone_index][curr_min_step] = 1;
		}

		stone_position++;
		curr_min_step++;

		if (stone_index < stonesSize && stones[stone_index] < stone_position)
		{
			stone_index++;
		}

		if (stone_index < stonesSize && stones[stone_index] == stone_position && !visited[stone_index][curr_min_step])
		{
			curr = &queue[tail++];
			curr->stone_index = stone_index;
			curr->min_step = curr_min_step;
			visited[stone_index][curr_min_step] = 1;
		}
	}

	return false;
}

bool canCross(int* stones, int stonesSize) {
	int **visited;
	struct record *queue;
	bool res;
	int i;

	if (stones[1] != 1) return false;
	if (stonesSize == 2) return true;

	visited = (int **)malloc(sizeof(*visited) * stonesSize);

	for (i = 0; i < stonesSize; i++)
	{
		visited[i] = (int *)malloc(sizeof(*visited[0]) * stonesSize);
		memset(visited[i], 0, sizeof(*visited[0]) * stonesSize);
	}

	queue = (struct record *)malloc(sizeof(*queue) * stonesSize * stonesSize);
	
	res = can_cross(stones, stonesSize, visited, queue);

	for (i = 0; i < stonesSize; i++)
	{
		free(visited[i]);
	}

	free(visited);
	free(queue);

	return res;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值