剑指offer:33-37记录

举报
兔老大 发表于 2021/04/22 23:08:23 2021/04/22
【摘要】 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。   参考以下这颗二叉搜索树:      5     / \    2   6   / \  ...

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

 

参考以下这颗二叉搜索树:

     5
    / \
   2   6
  / \
 1   3
示例 1:

输入: [1,6,3,2,5]
输出: false
示例 2:

输入: [1,3,2,6,5]
输出: true
 

提示:

数组长度 <= 1000

思路:找到第一个比根大的数字x,x右边所有数字都要比根大才符合定义。

然后对左右子树重复上述过程。


  
  1. class Solution {
  2. int[] postorder;
  3. public boolean verifyPostorder(int[] postorder) {
  4. this.postorder=postorder;
  5. return verify(0, postorder.length - 1);
  6. }
  7. // 递归实现
  8. private boolean verify(int left, int right){
  9. if (left >= right) return true;
  10. int rootValue = postorder[right]; // 当前根
  11. // 找出第一个大于根节点的,右边必须都在右子树中
  12. int k = left;
  13. while (k < right && postorder[k] < rootValue){
  14. k++;
  15. }
  16. //判断
  17. for (int i = k; i < right; i++){
  18. if (postorder[i] < rootValue) return false;
  19. }
  20. return verify(left, k - 1) && verify(k, right - 1);
  21. }
  22. }

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

 

示例:
给定如下二叉树,以及目标和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
返回:

[
   [5,4,11,2],
   [5,8,4,5]
]

提示:

节点总数 <= 10000

思路:深搜+回溯


  
  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. List<List<Integer>> ans=new ArrayList();
  12. List<Integer> temp=new ArrayList();
  13. public List<List<Integer>> pathSum(TreeNode root, int sum) {
  14. help(root,sum);
  15. return ans;
  16. }
  17. public void help(TreeNode root, int sum){
  18. if(root==null)return;
  19. temp.add(root.val);
  20. sum-=root.val;
  21. if(sum==0 && root.left==null && root.right==null){
  22. ans.add(new ArrayList(temp));
  23. }
  24. help(root.left,sum);
  25. help(root.right,sum);
  26. temp.remove(temp.size() - 1);
  27. }
  28. }

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

示例 1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
 

提示:

-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。

思路:先把每个节点后面复制一个相同的节点,为了方便处理好random。然后再分开即可。

空间O(1)


  
  1. /*
  2. // Definition for a Node.
  3. class Node {
  4. int val;
  5. Node next;
  6. Node random;
  7. public Node(int val) {
  8. this.val = val;
  9. this.next = null;
  10. this.random = null;
  11. }
  12. }
  13. */
  14. class Solution {
  15. public Node copyRandomList(Node head) {
  16. if (head == null) {
  17. return head;
  18. }
  19. //将拷贝节点放到原节点后面,例如1->2->3这样的链表就变成了这样1->1'->2'->3->3'
  20. for (Node node = head, copy = null; node != null; node = node.next.next) {
  21. copy = new Node(node.val);
  22. copy.next = node.next;
  23. node.next = copy;
  24. }
  25. //把拷贝节点的random指针安排上
  26. for (Node node = head; node != null; node = node.next.next) {
  27. if (node.random != null) {
  28. node.next.random = node.random.next;
  29. }
  30. }
  31. //分离拷贝节点和原节点,变成1->2->3和1'->2'->3'两个链表,后者就是答案
  32. Node newHead = head.next;
  33. for (Node node = head, temp = null; node != null && node.next != null;) {
  34. temp = node.next;
  35. node.next = temp.next;
  36. node = temp;
  37. }
  38. return newHead;
  39. }
  40. }

序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。

请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

示例: 

你可以将以下二叉树:

    1
   / \
  2   3
     / \
    4   5

序列化为 "[1,2,3,null,null,4,5]"
提示: 这与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。

思路:我们普通的遍历(前序中序后序)序列,通常是不能唯一确定一个二叉树的,需要前中结合或者后中结合。是因为我们不知道哪里可以停止,比如例子中:到3时,我们不知道该挂到2的下面还是2两边都是null(3应该挂1的右边)。解决方法就是把所有的null记录下来,比如例子中的二叉树:前序:1,2,null,null,3,4,null,null,5,null,null。下面是在这种做法的实现。


  
  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. public class Codec {
  11. public String serialize(TreeNode root) { //用StringBuilder
  12. return ser_help(root, new StringBuilder()).toString();
  13. }
  14. public StringBuilder ser_help(TreeNode root, StringBuilder str){
  15. if(null == root){
  16. str.append("null,");
  17. return str;
  18. }
  19. str.append(root.val);
  20. str.append(",");
  21. str = ser_help(root.left, str);
  22. str = ser_help(root.right, str);
  23. return str;
  24. }
  25. public TreeNode deserialize(String data) {
  26. List<String> list_word = new LinkedList<String>(Arrays.asList(data.split(",")));
  27. return deser_help(list_word);
  28. }
  29. public TreeNode deser_help(List<String> li){
  30. if(li.get(0).equals("null")){
  31. li.remove(0);
  32. return null;
  33. }
  34. TreeNode res = new TreeNode(Integer.valueOf(li.get(0)));
  35. li.remove(0);
  36. res.left = deser_help(li);
  37. res.right = deser_help(li);
  38. return res;
  39. }
  40. }
  41. // Your Codec object will be instantiated and called as such:
  42. // Codec codec = new Codec();
  43. // codec.deserialize(codec.serialize(root));

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/104763833

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。