Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1...n.
For example,
Given n = 3, your program should return all 5 unique BST's shown below.
1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
是第96题的延伸,要求出所有可能性。
刚开始写了一个回溯法,但是由于没有办法在TreeNode中重写equals,导致需要重写的东西很多(主要这样做的话,一个一个添加TreeNode。会出现重复的情况),也就导致了时间很长。一百多ms。
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { List list = new ArrayList<TreeNode>(); public List<TreeNode> generateTrees(int n) { if( n == 0) return list; int[] pos = new int[n]; for( int i = 0;i<n;i++){ pos[i] = 1; TreeNode root = new TreeNode(i+1); getResult(root,pos); pos[i] = 0; } return list; } public void getResult(TreeNode root,int[] pos){ int flag = 0; for( int i = 0;i<pos.length;i++){ if( pos[i] == 0){ addNode(root,i); pos[i] = 1; getResult(root,pos); delNote(root,i); pos[i] = 0; flag = 1; } } if( flag == 0){ TreeNode ans = getAns(root); if( !isExist(ans) ) list.add(ans); } } public boolean isExist(TreeNode ans){ int size = list.size(); for( int i = 0;i<size;i++){ if( isSame((TreeNode)list.get(i),ans) ) return true; } return false; } public boolean isSame(TreeNode node1,TreeNode node2){ if( node1.val != node2.val) return false; if( node1.left != null && node2.left != null){ if( !isSame(node1.left,node2.left) ) return false; }else if( node1.left == null && node2.left == null) ; else return false; if( node1.right != null && node2.right != null){ if( !isSame(node1.right,node2.right) ) return false; }else if( node1.right == null && node2.right == null ) ; else return false; return true; } public TreeNode getAns(TreeNode root){ TreeNode ans = new TreeNode(root.val); if( root.left != null ) ans.left = getAns(root.left); if( root.right != null) ans.right = getAns(root.right); return ans; } public void addNode(TreeNode root,int i ){ while( true){ if( i+1 > root.val ){ if( root.right == null){ root.right = new TreeNode(i+1); return ; }else root = root.right; }else{ if( root.left == null){ root.left = new TreeNode(i+1); return ; }else root = root.left; } } } public void delNote(TreeNode root,int i){ while( true){ if( i+1 > root.val ){ if( i+1 == root.right.val ){ root.right = null; return ; }else root = root.right; }else{ if( i+1 == root.left.val ){ root.left = null; return ; }else root = root.left; } } } }
然后看了网上的解答,有两个我认为还不错,一个是根据树的结构来回溯,效率很高,不会出现重复,
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public List<TreeNode> generateTrees(int n) { if(n == 0) { return new ArrayList<TreeNode>(); } return gen(1, n); } List<TreeNode> gen(int start, int end) { ArrayList<TreeNode> heads = new ArrayList<TreeNode>(); if(start > end) { heads.add(null); return heads; } for(int i = start; i <= end; i++) { List<TreeNode> lefts = gen(start, i - 1); List<TreeNode> rights = gen(i + 1, end); for(TreeNode left : lefts) { for(TreeNode right : rights) { TreeNode head = new TreeNode(i); head.left = left; head.right = right; heads.add(head); } } } return heads; } }
还有一种动态规划其实也就是第二种方法的改良。
public static List<TreeNode> generateTrees(int n) { List<TreeNode>[] result = new List[n + 1]; result[0] = new ArrayList<TreeNode>(); if (n == 0) { return result[0]; } result[0].add(null); for (int len = 1; len <= n; len++) { result[len] = new ArrayList<TreeNode>(); for (int j = 0; j < len; j++) { for (TreeNode nodeL : result[j]) { for (TreeNode nodeR : result[len - j - 1]) { TreeNode node = new TreeNode(j + 1); node.left = nodeL; node.right = clone(nodeR, j + 1); result[len].add(node); } } } } return result[n]; } private static TreeNode clone(TreeNode n, int offset) { if (n == null) { return null; } TreeNode node = new TreeNode(n.val + offset); node.left = clone(n.left, offset); node.right = clone(n.right, offset); return node; }