输入一个整数数组,判断该数组是否是某二叉搜索树的后序遍历的结果。若是是则输出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. 七月算法 十月算法班 树和图