剑指offer系列题(21-25)

21.栈的压入、弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
题目思路
  • 如果下一个弹出的数字刚好是栈顶数字,那么直接弹出
  • 如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。
  • 如果所有的数字都压入栈了仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。
代码
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
          Stack<Integer> stack=new Stack<Integer>();
          for(int i=0,j=0;i<pushA.length;i++){
              stack.push(pushA[i]);
              while(stack.peek()==popA[j]){
                  stack.pop();
                  j++;
                  if(stack.empty()) break;
              }
          }
        if(!stack.empty()){
            return false;
        }else{
            return true;
        }
    }
}


22.从上往下打印二叉树
题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
题目思路
该题的思路就是树的层次遍历,跟图的广度优先搜索也类似。我们可以借助一个 数组一次存储树的节点。使用两个队列一个存放节点,一个存放值。先将根节点加入到队列中,然后遍历队列中的元素,遍历过程中,访问该元素的左右节点,再将左右子节点加入到队列中来。
题目代码
import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> al=new ArrayList<Integer>();
        ArrayList<TreeNode> al1=new ArrayList<TreeNode>();
        if(root==null){
          return al;
        }
        al1.add(root);
        while(al1.size()!=0){
            TreeNode tn=al1.remove(0);
            if(tn.left!=null){
                al1.add(tn.left);
            }
            if(tn.right!=null){
                al1.add(tn.right);
            }
            al.add(tn.val);
        }
        return al;
    }
}

23.二叉搜索树的后续遍历序列
题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
题目思路
该题需要我们首先清楚后续遍历的过程和二叉搜索树的特点,则可以发现后续遍历序列的规律。序列的最后一位是为根节点,除根节点外序列分为两个部分,前面一部分是为左子树小于根节点,后一部是为右子树,将全部大于根节点。
题目代码
import java.util.Arrays;
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length<=0){
            return false;
        }
        int i=0;
        for(;i<sequence.length;i++){
            if(sequence[i]>sequence[sequence.length-1]){
                break;
            }
        }
        int j=i;
        for(;j<sequence.length;j++){
            if(sequence[j]<sequence[sequence.length-1]){
                return false;
            }
       }
        boolean left=true;
        boolean right=true;
        if(i>0){
            left=VerifySquenceOfBST(Arrays.copyOf(sequence,i+1));
        }
        if(j<sequence.length-1){
             right=VerifySquenceOfBST(Arrays.copyOfRange(sequence,i+2,sequence.length-1));
        }
        return (left&&right);
   }  
}
24.二叉树和为某一值的路径
题目描述
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
题目思路
该题的思路是找到所有符合条件的list加入到list里面(嵌套list),凡是涉及到二叉树的算法,我们首先要想到递归。1.递归先序遍历树, 把结点加入路径。2.若该结点是叶子结点则比较当前路径和是否等于期待和。3.弹出结点,每一轮递归返回到父结点时,当前路径也应该回退一个结点。
题目代码
import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    private ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>();
    private ArrayList<Integer> list = new ArrayList<Integer>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        if(root == null) return listAll;
        list.add(root.val);
        target -= root.val;
        if(target == 0 && root.left == null && root.right == null)
            listAll.add(new ArrayList<Integer>(list));
        FindPath(root.left, target);
        FindPath(root.right, target);
        list.remove(list.size()-1);
        return listAll;
    }
}
25.复杂链表的复制
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
题目思路
该题是一个看起来比较复杂的题目,它要求对链表的操作非常的熟悉。我们可以采用分治的办法来降低算法的复杂性。通过三个子函数来实现我们想要的功能。one:构建与原链表相同的节点,并将它们添加至各个节点的后面,形成一个2*n的链表。two:复制每个节点的随机链接,因为有了第一步的操作,我们很方便就能找到克隆节点的随机指向。three:讲链表进行拆分,单数节点为原节点,双数节点为克隆节点。返回克隆节点。
代码
/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
       {
       CloneNodes(pHead);
       ConnectNode(pHead);
      return ReconnectNode(pHead);
    }
    private void CloneNodes(RandomListNode pHead){
        RandomListNode pnode=pHead;
        while(pnode!=null){
            RandomListNode clonenode=new RandomListNode(0);
            clonenode.label=pnode.label;
            clonenode.next=pnode.next;
            pnode.next=clonenode;
            pnode=clonenode.next;
        }
    }
   private void ConnectNode(RandomListNode pHead){
       RandomListNode pnode=pHead;
       while(pnode!=null){
           RandomListNode clonenode=pnode.next;
           if(pnode.random!=null){
               clonenode.random=pnode.random.next;
           }else{
               clonenode.random=null;
           }
           pnode=clonenode.next;
       }
   }
    private RandomListNode ReconnectNode(RandomListNode pHead){
        RandomListNode pnode =pHead;
        RandomListNode cloneHead =null;
        RandomListNode clonepnode =null;
        if(pnode!=null){
            cloneHead =pnode.next;
            clonepnode=pnode.next;
            pnode.next=cloneHead.next;
            pnode =pnode.next;
        }
        while(pnode!=null){
            clonepnode.next=pnode.next;
            clonepnode=clonepnode.next;
            pnode.next=clonepnode.next;
            pnode=pnode.next;
        }
        return cloneHead;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值