作者 Drizzle
单位 山东科技大学
我跳累了~😢
人活着本没有意义,但只有活着就会碰到很多有趣的事,就像你发现了花,而我发现了你一样。
这里有一段整数数组nums,你一开始处于下标为0的第一个元素处,请求出你最少跳几次能到达数组的末尾位置。
当你在i
位置时可以跳跃到一下三个位置:
i + 1
:i+1 < nums.lengthi - 1
:i-1 >= 0j
:nums[i] == nums[j]
输入:
第一行输入n表示nums的长度
第二行以空格分隔输入nums的每个元素
11
11 22 7 7 7 7 7 7 7 22 13
输出:
输出一行最小跳跃次数
3
范围:
- 1 <= nums.length <= 5 * 104
- -108<= nums[i] <= 108
样例解释:
其实我觉得题面解释蛮清楚滴!但是有人可能还有点疑惑。 总共有1个数组,11个数。 你可以把这11个数看成有编号的11个格子, 第1 个格子的下标是0, 格子的值是11 第11个格子的下标是10,格子的值是13 你在下标是1-9的格子都可以进行: 假设你在下标是i的格子上。其中i是1-9的任意一个数。 1.向前跳一步,跳到下标是:i + 1的格子上 2.向后跳一步,跳到下标是:i - 1的格子上 3.你还可以:假设当前格子值是v。那么你可以跳到任意的值也是v的格子上。 你在下标是0的时候不能向后跳。 你在下标是10的时候不能向前跳。 对于这组样例呢, 你看 下标:0 1 2 3 4 5 6 7 8 9 10 数值:11 22 7 7 7 7 7 7 7 22 13 开始在下标0, 跳到下标1,(值为22,可以向前跳一步),共计跳跃1次。 跳到下标9,(值为22,相同的值可以相互跳!),共计跳跃2次。 跳到下标10,(值为13,可以向前跳一步),共计跳跃3次。 如有解释失误欢迎把dayi祭天。
代码长度限制
16 KB
时间限制
1000 ms
内存限制
100 MB
//本题的bfs逻辑相对较乱,需要慢慢理解,特别是v和vis_cnt的关系
#include <bits/stdc++.h>
#define int long long
#define close_stdin ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 50010;
int n,cnt,num[N],vis[N],step[N];
map<int,int> vis_cnt;//记录每一个数字在vector v中是第几个
vector<int> v[N];//vector中0~v[i].size - 1储存的是相同的数字的不同位置
//例如题目中样例的数字7,它第一次出现是在第3位,因此vis_cnt[7] = 3;
//而7这个数字在第3,4,5,6,7,8,9位中都出现过,因此把3,4,5,6,7,8,9都添加进v[3]中
//便于我们在bfs时,快速寻找到7这个数字所在的位置
int c[3] = {1,-1};
void bfs(int x)
{
int t = x;
vis[t] = 1;
queue<int> q;
q.push(t);
while (!q.empty())
{
t = q.front();
q.pop();
for (int i = 0 ; i < 2 ; i ++) //往左往右走的情况,也就是i - 1,i + 1
{
int tt = t + c[i];
if (1 <= tt && tt <= n)
{
if (vis[tt] == 0)
{
vis[tt] = 1;
step[tt] = step[t] + 1;
q.push(tt);
}
}
}
//vis_cnt[num[t]]的解释:
//t是当前在bfs第几位
//num[t]是第t位在数组中存的数
//vis_cnt[num[t]]是指这个数在在v中是第几个出现的
for (int i = 0 ; i < v[vis_cnt[num[t]]].size() ; i ++)//处理num[i] == num[j]的情况
{
int tt = v[vis_cnt[num[t]]][i];
if (1 <= tt && tt <= n)
{
if (vis[tt] == 0)
{
vis[tt] = 1;
step[tt] = step[t] + 1;
q.push(tt);
}
}
}
}
}
void solve()
{
cnt = 1;
cin >> n;
for (int i = 1 ; i <= n ; i ++)
{
int tmp;
cin >> tmp;
num[i] = tmp;
if (vis_cnt[tmp] == 0)//判断当前这种数字有没有出现过
{
vis_cnt[tmp] = cnt;//没出现过则标记是在第几次出现这个数
cnt ++;
}
int now = vis_cnt[tmp];//这个数在第now次出现
v[now].push_back(i);//将第i位,并入和它数字相同的vector里
}
bfs(1);
cout << step[n] << endl;
}
signed main ()
{
close_stdin;
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}