Skip to content

Commit 37c0ac4

Browse files
左程云左程云
authored andcommitted
add problem 55 follow up
1 parent 12683a5 commit 37c0ac4

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package topinterviewquestions;
2+
3+
import java.util.HashMap;
4+
import java.util.LinkedList;
5+
import java.util.Queue;
6+
7+
public class Problem_0055_JumpMinTimesFollowUpOnClass {
8+
9+
public static int jumpMinTimes1(int N, int start, int end, int[] arr) {
10+
boolean[] map = new boolean[N + 1];
11+
12+
return f1(N, start, end, 0, arr, map);
13+
}
14+
15+
// 一共有N个位置, 每个位置如何跳,记录在arr中
16+
// 之前一共走了步数是step步
17+
// 当前来到cur位置,最终想去aim位置,
18+
// 返回从start开始到aim,最少的步数
19+
// 如果map[i] == true 表示i位置,之前来过
20+
// 如果map[i] == false 表示i位置,之前没来过
21+
public static int f1(int N, int cur, int aim, int step, int[] arr, boolean[] map) {
22+
if (cur < 1 || cur > N) {
23+
return -1;
24+
}
25+
if (map[cur]) {
26+
return -1;
27+
}
28+
// 有效的位置,又没来过
29+
if (cur == aim) {
30+
return step;
31+
}
32+
map[cur] = true;
33+
int ans1 = f1(N, cur + arr[cur - 1], aim, step + 1, arr, map);
34+
int ans2 = f1(N, cur - arr[cur - 1], aim, step + 1, arr, map);
35+
map[cur] = false;
36+
if (ans1 != -1 && ans2 != -1) {
37+
return Math.min(ans1, ans2);
38+
}
39+
if (ans1 != -1 && ans2 == -1) {
40+
return ans1;
41+
}
42+
if (ans1 == -1 && ans2 != -1) {
43+
return ans2;
44+
}
45+
return -1;
46+
}
47+
48+
// 一共有N个位置
49+
// 最终要去aim位置
50+
// arr中,描述怎么跳
51+
// 当前,来到了i位置
52+
// 已经走了k步
53+
// 最后到达aim,至少几步?
54+
public static int process(int N, int aim, int[] arr, int i, int k) {
55+
if (i < 1 || i > N || k > N - 1) {
56+
return -1;
57+
}
58+
if (i == aim) {
59+
return k;
60+
}
61+
// 请注意,arr的下标是从0开始的,但是题目规定的下标从1开始
62+
// 所以,拿出i位置能跳的距离,需要拿arr[i-1]位置的值
63+
int ans1 = process(N, aim, arr, i + arr[i - 1], k + 1);
64+
int ans2 = process(N, aim, arr, i - arr[i - 1], k + 1);
65+
int ans = -1;
66+
if (ans1 != -1 && ans2 != -1) {
67+
ans = Math.min(ans1, ans2);
68+
}
69+
if (ans1 != -1 && ans2 == -1) {
70+
ans = ans1;
71+
}
72+
if (ans1 == -1 && ans2 != -1) {
73+
ans = ans2;
74+
}
75+
return ans;
76+
}
77+
78+
public static int jumpMinTimes2(int N, int start, int end, int[] arr) {
79+
int[][] dp = new int[N + 1][N + 1];
80+
for (int i = 0; i < dp.length; i++) {
81+
for (int j = 0; j < dp[0].length; j++) {
82+
dp[i][j] = -2;
83+
}
84+
}
85+
// dp[i][k] == -2表示这个过程没算过
86+
// dp[i][k] != -2表示这个过程算过了
87+
return f2(N, end, arr, start, 0, dp);
88+
}
89+
90+
// 一共有N个位置,跳的过程中,如果你又跳回到某个位置,其实这已经说明不是最优步数了
91+
// 也就是说,如果存在最优的跳法,那么这个最优跳法一定不会大于N-1步
92+
// 所以,增加了一个参数k,表示已经跳了多少步
93+
// 整个函数的含义:
94+
// 一共有1~N个位置,目标是aim位置
95+
// 所有位置能跳的距离都记录在arr中,并且对任意的arr[i] > 0
96+
// 当前来到的位置是i, 之前已经跳过了k步,
97+
// 返回最后到达aim位置,跳的最少的步数
98+
// 如果返回-1表示怎么也无法到达
99+
public static int f2(int N, int aim, int[] arr, int i, int k, int[][] dp) {
100+
if (i < 1 || i > N || k > N - 1) {
101+
return -1;
102+
}
103+
if (dp[i][k] != -2) {
104+
return dp[i][k];
105+
}
106+
if (i == aim) {
107+
dp[i][k] = k;
108+
return k;
109+
}
110+
// 请注意,arr的下标是从0开始的,但是题目规定的下标从1开始
111+
// 所以,拿出i位置能跳的距离,需要拿arr[i-1]位置的值
112+
int ans1 = f2(N, aim, arr, i + arr[i - 1], k + 1, dp);
113+
int ans2 = f2(N, aim, arr, i - arr[i - 1], k + 1, dp);
114+
int ans = -1;
115+
if (ans1 != -1 && ans2 != -1) {
116+
ans = Math.min(ans1, ans2);
117+
}
118+
if (ans1 != -1 && ans2 == -1) {
119+
ans = ans1;
120+
}
121+
if (ans1 == -1 && ans2 != -1) {
122+
ans = ans2;
123+
}
124+
dp[i][k] = ans;
125+
return ans;
126+
}
127+
128+
// bfs
129+
public static int jumpMinTimes3(int N, int start, int end, int[] arr) {
130+
if (start < 1 || start > N || end < 1 || end > N) {
131+
return -1;
132+
}
133+
Queue<Integer> queue = new LinkedList<>();
134+
HashMap<Integer, Integer> levelMap = new HashMap<>();
135+
queue.add(start);
136+
levelMap.put(start, 0);
137+
while (!queue.isEmpty()) {
138+
int cur = queue.poll();
139+
int level = levelMap.get(cur);
140+
if (cur == end) {
141+
return level;
142+
} else {
143+
int left = cur - arr[cur - 1];
144+
int right = cur + arr[cur - 1];
145+
if (left > 0 && !levelMap.containsKey(left)) {
146+
queue.add(left);
147+
levelMap.put(left, level + 1);
148+
}
149+
if (right <= N && !levelMap.containsKey(right)) {
150+
queue.add(right);
151+
levelMap.put(right, level + 1);
152+
}
153+
}
154+
}
155+
return -1;
156+
}
157+
158+
// for test
159+
public static int[] gerRandomArray(int N, int R) {
160+
int[] arr = new int[N];
161+
for (int i = 0; i < N; i++) {
162+
arr[i] = (int) (Math.random() * R);
163+
}
164+
return arr;
165+
}
166+
167+
public static void printArray(int[] arr) {
168+
for (int i = 0; i < arr.length; i++) {
169+
System.out.print(arr[i] + " ");
170+
}
171+
System.out.println();
172+
}
173+
174+
public static void main(String[] args) {
175+
int maxN = 20;
176+
int maxV = 10;
177+
int testTimes = 200000;
178+
System.out.println("test begin");
179+
for (int i = 0; i < testTimes; i++) {
180+
int[] arr = gerRandomArray(maxN, maxV);
181+
int N = arr.length;
182+
int start = (int) (Math.random() * N) + 1;
183+
int end = (int) (Math.random() * N) + 1;
184+
int ans1 = jumpMinTimes1(N, start, end, arr);
185+
int ans2 = jumpMinTimes2(N, start, end, arr);
186+
int ans3 = jumpMinTimes3(N, start, end, arr);
187+
if (ans1 != ans2 || ans2 != ans3) {
188+
printArray(arr);
189+
System.out.println("start : " + start);
190+
System.out.println("end : " + end);
191+
System.out.println("ans1 : " + ans1);
192+
System.out.println("ans2 : " + ans2);
193+
System.out.println("ans3 : " + ans2);
194+
System.out.println("Oops!");
195+
break;
196+
}
197+
}
198+
System.out.println("test end");
199+
}
200+
201+
}

0 commit comments

Comments
 (0)