笔试题-跳格子游戏,Java代码
題目詳情
標題:跳格子游戲 | 時間限制:1秒 | 內存限制:262144K | 語言限制:不限
地上共有N個格子,你需要跳完地上所有的格子,但是格子間是有強依賴關系的,跳完前一個格子后,后續的格子才會被開啟,格子間的依賴關系由多組steps數組給出,steps[0]表示前一個格子,steps[1]表示steps[0]可以開啟的格子:
比如[0,1]表示從跳完第0個格子以后第1個格子就開啟了,比如[2,1],[2,3]表示跳完第2個格子后第1個格子和第3個格子就被開啟了
請你計算是否能由給出的steps數組跳完所有的格子,如果可以輸出yes,否則輸出no
說明:
1.你可以從一個格子跳到任意一個開啟的格子
2.沒有前置依賴條件的格子默認就是開啟的
3.如果總數是N,則所有的格子編號為[0,1,2,3…N-1]連續的數組
輸入描述:
輸入一個整數N表示總共有多少個格子,接著輸入多組二維數組steps表示所有格子之間的依賴關系
輸出描述:
如果能按照steps給定的依賴順序跳完所有的格子輸出yes
否則輸出no
示例1
輸入
3
0 1
0 2
輸出
yes
說明
總共有三個格子[0,1,2],跳完0個格子后第1個格子就開啟了,跳到第0個格子后第2個格子也被開啟了,按照0->1->2或者0->2->1的順序都可以跳完所有的格子
示例2
輸入
2
1 0
0 1
輸出
no
說明
總共有2個格子,第1個格子可以開啟第0格子,但是第1個格子又需要第0個格子才能開啟,相互依賴,因此無法完成
示例3
輸入
6
0 1
0 2
0 3
0 4
0 5
輸出
yes
說明
總共有6個格子,第0個格子可以開啟第1,2,3,4,5個格子,所以跳完第0個格子之后其他格子都被開啟了,之后按任何順序可以跳完剩余的格子
示例4
輸入
5
4 3
0 4
2 1
3 2
輸出
yes
說明
跳完第0個格子可以開啟格子4,跳完格子4可以開啟格子3,跳完格子3可以開啟格子2,跳完格子2可以開啟格子1,按照0->4->3->2->1這樣就跳完所有的格子
示例5
輸入
4
1 2
1 0
輸出
yes
說明
總共4個格子[0,1,2,3],格子1和格子3沒有前置條件所以默認開啟,格子1可以開啟格子0和格子2,所以跳到格子1之后就可以開啟所有的格子,因此可以跳完所有格子
解題思路
很明顯這是一道拓撲排序題目,不同的節點之間存在先后執行依賴關系,只有前一個節點完成后一個節點才能完成。比如以下面例子
6
1 2
1 3
1 4
0 2
0 3
3 1
為例子,有拓撲圖如下所示:
edges是一個長度N為的List集合,以steps格子的右邊數據(即開啟的格子)為索引,以依賴關系的左邊數據作為list的相鄰頂點集合。節點5是一個單獨節點。
可以使用深度搜索或者廣度搜索來遍歷圖中的每個節點以及其相鄰節點,如果判斷圖中存在環,那么一定有兩個格子相互依賴,也就無法跳完所有的格子。以深度搜索dfs為例說明,如何判別圖中是否存在環呢?針對某個節點來說,遍歷其有三種可能:
-
這個節點還未被遍歷過,這種情況會將這個節點加入dfs里面遞歸遍歷,直到某節點再無相鄰節點就結束。圖中0節點還沒被遍歷過,將節點0加入到dfs方法里面一直遍歷到節點4,節點4再無相鄰節點,符合條件。
-
這個節點已經被遍歷過了,但是在遍歷其相鄰節點時又遍歷了一次這個節點。比如節點0進入dfs深度遍歷,先是遍歷0的相鄰節點3,再遍歷相鄰節點1,接下來再次遍歷節點1的相鄰節點時是節點3而不是節點4,此時發現節點3已經被遍歷過了,那么圖中一定存在環,跳格子失敗。
- 這個節點被遍歷過了而且相鄰節點也被深度遍歷過了,說明圖中無環(單獨一個節點必然沒有環),可以跳完所有的格子。
想要對一個節點標記3中遍歷狀態,那么使用boolean數組是欠妥的,可以使用int數組,用整數0,1, 2表示一個節點的不同的遍歷狀態。
Java代碼
public class Main {private static final int NOT_VISITED = 0;private static final int VISITED = 1;private static final int VISIT_FINISHED = 2;static int[] visitStatus; //節點遍歷狀態static List<List<Integer>> edges; //記錄每個節點的相鄰節點static boolean stepAllGrids; //是否能跳完所有格子的結果判斷public static boolean step(int N,List<List<Integer>> edges) {visitStatus = new int[N]; //節點默認為0 ~ N - 1for(int i = 0; i < N && stepAllGrids; i++) { //總是從節點0開始進入if(visitStatus[i] == NOT_VISITED) {dfs(i);}}return stepAllGrids;}public static void dfs(int node) {visitStatus[node] = VISITED;for(int neighbor : edges.get(node)) { //遍歷相鄰節點if(visitStatus[neighbor] == NOT_VISITED) {dfs(neighbor);if(!stepAllGrids) { //如果退出循環時檢測到環,直接退出return;}}else if(visitStatus[neighbor] == VISITED){ //再一次遍歷到此節點,說明存在環,無法完成拓撲排序stepAllGrids = false;return;}}visitStatus[node] = VISIT_FINISHED;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);while(sc.hasNextLine()) {int N = sc.nextInt();if(N < 1 || N >= 500) {System.out.println("error:輸入的格子個數應該大于等于1且小于500");return;}edges = new ArrayList<>();for(int i = 0; i < N; i++) { //默認節點在0 ~ N - 1之間edges.add(new ArrayList<>());}stepAllGrids = true;while(sc.hasNext()) {int a = sc.nextInt();if(a == -1) { //題目缺失輸入退出條件,不妨設置輸入-1就退出輸入break;}String line = sc.nextLine();String[] strs = line.split(" ");if(strs.length != 2) {System.out.println("error:輸入的格子數組列數不為2");return;}if(a < 0 || a >= N) {System.out.println("error:輸入的左側格子號碼應該大于等于0且小于" + N);return;}int b = Integer.parseInt(strs[1]);if(b < 0 || b >= N) {System.out.println("error:輸入的右側格子號碼應該大于等于0且小于" + N);return;}edges.get(b).add(a);}if(step(N, edges)) {System.out.println("yes");}else {System.out.println("no");}}} }總結
以上是生活随笔為你收集整理的笔试题-跳格子游戏,Java代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广州HCNE之旅
- 下一篇: LinuxTomcat安装部署