輸入一個整數數組,判斷該數組是否是某二叉搜索樹的後序遍歷的結果。若是是則輸出Yes,不然輸出No。假設輸入的數組的任意兩個數字都互不相同。php
與此題類似的還有:java
如下序列中不多是一棵二叉查找樹的後序遍歷結果的是()算法
A. 1,2,3,4,5數組
B. 3,5,1,4,2數據結構
C. 1,2,5,4,3框架
D. 5,4,3,2,1this
思路:spa
因爲是後序遍歷序列,因此最後一個元素必定是根。那麼根據根能夠將剩下元素分紅兩部分,使得若是前半部分都小於根,後半部分都大於根。若是不存在這樣的劃分(例如上題的B,354不是連續的),則不可能有這樣的後序遍歷結果。.net
代碼:code
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner cin = new Scanner(System.in); int n; int[] arr = new int[10001]; while (cin.hasNextInt()) { n = cin.nextInt(); for (int i = 0; i < n; i++) { arr[i] = cin.nextInt(); } int root = arr[n - 1]; boolean flag = arr[0] - root > 0 ? true : false; int count = 1; for (int i = 1; i < n - 1; i++) { boolean temp = arr[i] - root > 0 ? true : false; if (flag != temp) { flag = temp; count--; if (count < 0) { break; } } } if (count < 0) { System.out.println("No"); } else { System.out.println("Yes"); } } } }
實現方法有不少,這裏不闡述了。
關於BFS的實現,在之前的Blog最短路徑算法已經介紹過了,就再也不次描述了。
這裏要談的是,到底什麼問題能夠歸爲BFS問題?
不僅僅是圖論上的問題,BFS中有一個特色就是:
若是在擴展某個中發現某結點在前期已經訪問過了,則本次再也不訪問該結點;顯然,第一次訪問到該結點時,是訪問次數最少的。
因此關於最少,最短的問題均可以想一下是否可以使用BFS的思想(例如最短路徑)
輔助數據結構:
算法描述:
1. 起點start入隊q
2. 若是隊列q非空,則隊首結點x出隊,嘗試擴展x
實踐中,每每乍看不是關於圖的問題,但若是是給定一個起始狀態和一些規則,求解決方案的問題,每每能夠根據這些規則,將各個狀態創建鏈接邊,而後使用BFS/DFS框架,一步步的在解空間中搜索。
給定字典和一個起點單詞和一個終點單詞,每次只能變換一個字母,問從起點單詞是否能夠到達終點單詞,最短多少步?
如:start="hit"
end ="cog"
dict=["hot","dot","dog","lot","log"]
"hit"->"hot"->"dot"->"dog"->"cog"
分析:
使用鄰接表,創建單詞間的聯繫:
單詞爲圖的結點,若可以變換成另外一個單詞,則兩個單詞間有無向邊(若A與B兩個單詞只有一個字母不一樣,則A與B之間有邊)
從起始單詞開始,廣度優先搜索,看可否到達終點單詞。若能夠到達,則這條路徑上的變化是最快的。
代碼:
import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; public class Solution { public int ladderLength(String beginWord, String endWord, Set<String> wordList) { Queue<String> queue = new LinkedList<String>(); queue.add(beginWord); List<String> children = new ArrayList<String>(); Map<String, Integer> step = new HashMap<String, Integer>(); step.put(beginWord, 1); while (!queue.isEmpty()) { String start = queue.poll(); children = findLinked(wordList, start, step); if (children.contains(endWord)) { return step.get(endWord); } else { queue.addAll(children); } } return 0; } public static List<String> findLinked(Set<String> wordList, String start, Map<String, Integer> step) { List<String> c = new ArrayList<String>(); for (Iterator iterator = wordList.iterator(); iterator.hasNext();) { String word = (String) iterator.next(); int diff = 0; for (int i = 0; i < start.length(); i++) { if (start.charAt(i) != word.charAt(i)) { diff++; } } if (diff == 1) { step.put(word, step.get(start) + 1); c.add(word); iterator.remove(); } } return c; } }
這種解法時間複雜度挺高的,至關於枚舉,不過可以解決問題。
給定二維平面,格點處要麼是「X」,要麼是「O」。求出全部「X」圍成的區域
例如:
X X X X X O O X X X O X X O X X
->(被圍起來的三個"O"轉換成"X")
X X X X X X X X X X X X X O X X
分析:
對於邊界的O必定是要保留的,那麼經過邊界的O可以BFS到的其餘O也是要保留的。剩下的O則變成X便可
代碼:
import java.util.LinkedList; import java.util.Queue; public class Solution { public static void solve(char[][] board) { if (board.length == 0) return; Queue<Node> queue = new LinkedList<Node>(); int n = board[0].length; int m = board.length; for (int i = 0; i < m; i++) { if (board[i][0] == 'O') { queue.add(new Node(i, 0)); board[i][0] = 'Y'; } if (board[i][n - 1] == 'O') { queue.add(new Node(i, n - 1)); board[i][n - 1] = 'Y'; } } for (int i = 1; i < n - 1; i++) { if (board[0][i] == 'O') { queue.add(new Node(0, i)); board[0][i] = 'Y'; } if (board[m - 1][i] == 'O') { queue.add(new Node(m - 1, i)); board[m - 1][i] = 'Y'; } } while (!queue.isEmpty()) { Node startNode = queue.poll(); findO(startNode, board, queue, m, n); } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (board[i][j] == 'O') board[i][j] = 'X'; } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (board[i][j] == 'Y') board[i][j] = 'O'; } } } public static void findO(Node startNode, char[][] board, Queue<Node> queue, int m, int n) { int x = startNode.x; int y = startNode.y; while ((++x < m) && (board[x][y] == 'O')) { board[x][y] = 'Y'; queue.add(new Node(x, y)); } x = startNode.x; y = startNode.y; while ((--x > 0) && (board[x][y] == 'O')) { board[x][y] = 'Y'; queue.add(new Node(x, y)); } x = startNode.x; y = startNode.y; while ((--y > 0) && (board[x][y] == 'O')) { board[x][y] = 'Y'; queue.add(new Node(x, y)); } x = startNode.x; y = startNode.y; while ((++y < n) && (board[x][y] == 'O')) { board[x][y] = 'Y'; queue.add(new Node(x, y)); } } public static void main(String[] args) { char[][] c = new char[3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { c[i][j] = 'O'; } } solve(c); } } class Node { int x, y; public Node(int x, int y) { this.x = x; this.y = y; } }
通常所謂「暴力枚舉」搜索都是指DFS
通常使用堆棧或者遞歸
得到的信息:時間戳,顏色,父子關係,高度
1. 七月算法 十月算法班 樹和圖