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

mac2024-06-04  39

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)