最近写数据结构有关于树的题目时的一些心得。
发现针对不同题目采用不同的遍历方式(前序,中序,后序)解题,会使得解题的难易程度有明显的不同。
就比如关于一道判定是否为二叉搜索树的题目
二叉搜索树是指对每一节点,左子树的节点严格小于该节点,右子树的节点严格大于该节点。
而这样的结构,中序遍历产生的序列会恰好是一个升序序列(若访问的树是二叉搜素树),因而只要对产生的序列进行判断是否为递增,则快速判断是否为二叉搜索树。
我的代码如下:
class Solution {
Deque<TreeNode> treelist = new ArrayDeque<>();
public boolean isValidBST(TreeNode root) {
if(root==null)return true;
boolean an1 = isValidBST(root.left);
if(!treelist.isEmpty()&&treelist.getLast().val>=root.val)
return false;
else treelist.addLast(root);
boolean ans2 = isValidBST(root.right);
return an1&&ans2;
}
}
设定了一个栈,来放置元素,每次都和栈顶元素(栈顶元素为上一个节点)的值进行比较,一旦发现失衡现象(即出现非递增情况),则返回false。
还有一道关于对称二叉树的题目,对称二叉树指他们是否镜像对称。
其实为了代码编写更为清晰,可以先将子树进行反转,然后比较他们是否相等。
代码如下:
/*翻转函数,递归进行。对于一个子树,翻转它,实际上就是递归至最深处,然后依次回溯,将他的每一个结点的左右节点交换。
*/
public void MirrorTree(TreeNode root) {
if(root==null) return;
MirrorTree(root.left);
MirrorTree(root.right);
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
return;
}
/*判断是否相等的函数,注意,若一边为null,一边不为null,此种情况并非相等。依次递归,返回每一颗子树的的相等情况。
*/
public boolean isSame(TreeNode left,TreeNode right) {
if(left==null&&right==null) return true;
if(left!=null&&right!=null&&left.val==right.val&&
isSame(left.left, right.left)&&isSame(left.right, right.right)
)return true;
else return false;
}
public boolean isSymmetric(TreeNode root) {
if(root==null) {
return true;
}
MirrorTree(root.left);
return isSame(root.left, root.right);
}
非翻转代码,可以用队列来进行节点的存储,而开头的根节点,放入两次,运用广度优先算法,逐层放入节点,注意,放置节点时,应从两侧依次放入节点,以保证每次放入的节点都是在位置上对称的,然后每次取出两个节点,进行比较。
class Solution {
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> deque = new LinkedList<TreeNode>();
deque.offer(root);
deque.offer(root);
while(!deque.isEmpty()) {
TreeNode left = deque.poll();
TreeNode right = deque.poll();
if(left==null&&right==null)continue;
if(left==null||right==null) return false;
if(left.val!=right.val)return false;
deque.offer(left.left);
deque.offer(right.right);
deque.offer(left.right);
deque.offer(right.left);
}
return true;
}
}
递归转非递归时,往往会增添一个队列或栈结构,以还原递归算法的状态。