剑指Offer学习 【面试题23:从上往下打印二叉树】【面试题24:二叉搜索树的后序遍历序列】【面试题25:二叉树中和为某一值的路径】【面试题26:复杂链表的复制】

23题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左向右的顺序打印。

public class Offer23 {

	public static class BinaryTreeNode{
		int value;
		BinaryTreeNode left;
		BinaryTreeNode right;
	}
	
	public static void printFromToBottom(BinaryTreeNode root){
//		如果节点为非空
		if(root != null){
			Queue<BinaryTreeNode> list = new LinkedList<>();
//			根节点入队
			list.add(root);
//			记录当前处理节点
			BinaryTreeNode curNode;
			
//			如果队列非空,则进行处理
			while(!list.isEmpty()){
//				删除首节点,即正在处理节点
				curNode = list.remove();
//				输出元素值
				System.out.print(curNode.value+" ");
//				若子节点存在,则入队
				if(curNode.left != null){
					list.add(curNode.left);
				}
				if(curNode.right != null){
					list.add(curNode.right);
				}
			}
		}
	}
	
	
	public static void main(String[] args) {

        //       8
        //    /    \
        //   6     10
        //  / \   / \
        // 5   7 9  11
        BinaryTreeNode root = new BinaryTreeNode();
        root.value = 8;
        root.left = new BinaryTreeNode();
        root.left.value = 6;
        root.left.left = new BinaryTreeNode();
        root.left.left.value = 5;
        root.left.right = new BinaryTreeNode();
        root.left.right.value = 7;
        root.right = new BinaryTreeNode();
        root.right.value = 10;
        root.right.left = new BinaryTreeNode();
        root.right.left.value = 9;
        root.right.right = new BinaryTreeNode();
        root.right.right.value = 11;
        printFromToBottom(root);

        //         1
        //        /
        //       3
        //      /
        //     5
        //    /
        //   7
        //  /
        // 9
        BinaryTreeNode root2 = new BinaryTreeNode();
        root2.value = 1;
        root2.left = new BinaryTreeNode();
        root2.left.value = 3;
        root2.left.left = new BinaryTreeNode();
        root2.left.left.value = 5;
        root2.left.left.left = new BinaryTreeNode();
        root2.left.left.left.value = 7;
        root2.left.left.left.left = new BinaryTreeNode();
        root2.left.left.left.left.value = 9;
        System.out.println("\n");
        printFromToBottom(root2);

        // 0
        //  \
        //   2
        //    \
        //     4
        //      \
        //       6
        //        \
        //         8
        BinaryTreeNode root3 = new BinaryTreeNode();
        root3.value = 0;
        root3.right = new BinaryTreeNode();
        root3.right.value = 2;
        root3.right.right = new BinaryTreeNode();
        root3.right.right.value = 4;
        root3.right.right.right = new BinaryTreeNode();
        root3.right.right.right.value = 6;
        root3.right.right.right.right = new BinaryTreeNode();
        root3.right.right.right.right.value = 8;
        System.out.println("\n");
        printFromToBottom(root3);

        // 1
        BinaryTreeNode root4 = new BinaryTreeNode();
        root4.value = 1;
        System.out.println("\n");
        printFromToBottom(root4);

        // null
        System.out.println("\n");
        printFromToBottom(null);

    }
}

24题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true。否则返回false。假设输入的数组的任意两个数字都互不相同。

public class Offer24 {

	/**
	 * 二叉搜索树:
	 * 若左子树不空,则左子树上所有节点值均小于根节点值,
	 * 若右子树不空,则右子树所有节点值均大于根节点值
	 * 
	 */
	public static boolean verifySequenceOfBST(int[] sequence){
//		输入验证
		if(sequence == null || sequence.length <= 0){
			return false;
		}
		return verifySequenceOfBST(sequence, 0, sequence.length-1);
	}

	/**
	 * 输入一个整数数组,判断是否为二叉搜索树的后序遍历的结果
	 * @param sequence
	 * @param i
	 * @param j
	 * @return
	 */
	private static boolean verifySequenceOfBST(int[] sequence, int start, int end) {
		
//		如果对应要处理的数据只有一个或者没有数据要处理
		if(start >= end){
			return true;
		}
		int index = start;
//		找到第一个不小于根节点的元素的位置
		while(index < end-1 && sequence[index] < sequence[end]){
			index++;
		}
//		[start, index-1]为左子树, [index, end-1]为右子树
		int right = index;
		while(index < end-1 && sequence[index] > sequence[end]){
			index++;
		}
//		如果符合二叉搜索树,那么index应为end-1
		if(index != end-1){
			return false;
		}
		
//		如果以上合法,则递归执行
		return verifySequenceOfBST(sequence, start, right-1) && verifySequenceOfBST(sequence, right, end-1);
	}
}

25题目:输入一棵二叉树和一个整数, 打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

public class Offer25 {

	public static class BinaryTreeNode{
		int value;
		BinaryTreeNode left;
		BinaryTreeNode right;
	}
	
	/**
	 * 输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径
	 */
	public static void findPath(BinaryTreeNode root, int expectedSum){
//		创建一个链表,用于存放根节点到当前处理节点所经过的节点
		List<Integer> list = new ArrayList<Integer>();
		if(root != null){
			findPath(root, 0, expectedSum, list);
		}
	}

	private static void findPath(BinaryTreeNode root, int curSum, int expectedSum, List<Integer> result) {
		
		if(root != null){
			curSum += root.value;
			result.add(root.value);
			if(curSum < expectedSum){
//				递归处理左子树
				findPath(root.left, curSum, expectedSum, result);
//				递归处理右子树
				findPath(root.right, curSum, expectedSum, result);
			}else if(curSum == expectedSum){
//				当前节点是叶节点,输出结果
				if(root.left == null && root.right == null){
					System.out.println(result);
				}
			}
//			移除当前节点
			result.remove(result.size()-1);
		}
	}
}

26题目:请实现函数ComplexListNode clone(ComplexListNode head),复制一个复杂链表。在复杂链表中,每个结点除了有一个next 域指向下一个结点外,还有一个sibling 指向链表中的任意结点或者null。

public class Offer26 {

	public static class ComplexListNode{
		int value;
		ComplexListNode next;
		ComplexListNode sibling;
	}
	
	public static ComplexListNode clone(ComplexListNode head){
		if(head == null){
			return null;
		}
		
//		根据我们的思路分为三步:
//		1. 复制节点
		cloneNodes(head);
//		2. 链接sibling字段
		connectNodes(head);
//		3. 将整个链表拆分,返回复制链表的头结点
		return reconnectNodes(head);
	}
	
	/**
	 * 输出链表信息
	 */
	public static void printList(ComplexListNode head){
		while(head != null){
			System.out.print(head.value + "->");
			head = head.next;
		}
		System.out.println("null");
	}
	
	/**
	 * 判断两个链表是否是同一个链表
	 */
	public static boolean isSame(ComplexListNode h1, ComplexListNode h2){
		while(h1 != null && h2 != null){
			if(h1 == h2){
				h1 = h1.next;
				h2 = h2.next;
			}else{
				return false;
			}
		}
		return h1 == null && h2 == null;
	}

	/**
	 * 将刚复制的节点和被复制的节点分离开,还原被复制的链表,同事生成复制链表
	 * @param head
	 * @return
	 */
	private static ComplexListNode reconnectNodes(ComplexListNode head) {
		
		if(head == null){
			return null;
		}
//		记录复制链表的头结点
		ComplexListNode newHead = head.next;
//		记录当前处理的复制节点
		ComplexListNode pointer = newHead;
//		被复制节点的next指向下一个被复制节点
		head.next = newHead.next;
//		指向新的被复制节点
		head = head.next;
		
		while(head != null){
//			pointer指向复制节点
			pointer.next = head.next;
			pointer = pointer.next;
//			head的下一个指向复制节点的下一个节点,即原来链表的节点
			head.next = pointer.next;
//			head指向下一个原来链表上的节点
			head = pointer.next;
		}
		return newHead;
	}

	/**
	 * 设置复制节点的sibling字段
	 * @param head
	 */
	private static void connectNodes(ComplexListNode head) {
	
		while(head != null){
//			如果当前节点的sibling字段不为空,则进行复制
			if(head.sibling != null){
//				此时head.sibling表示被复制的节点的sibling所指向的节点
//				那么它的下一个节点就是我们要找的节点
				head.next.sibling = head.sibling.next;
			}
			head = head.next.next;
		}
	}

	/**
	 * 复制一个链表,将复制后的节点插入到被复制的节点后面,只连接复制节点的next字段
	 * @param head
	 */
	private static void cloneNodes(ComplexListNode head) {
	
		while(head != null){
//			创建一个新的节点
			ComplexListNode tmp = new ComplexListNode();
			tmp.value = head.value;
			tmp.next = head.next;
			head.next = tmp;
//			指向下一个要进行复制的节点
			head = tmp.next;
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值