剑指Offer【牛客网】刷题(五)

21、栈的压入、弹出序列

题目描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
解题思路:先找到当前pop序列第一个数对应push序列数的下标,从这个下标push序列往前遍历,pop序列往后遍历,有相等的数便在push队列中去掉这个数,直到没有出栈的数,记住当前下标index1,继续寻找pop队列当前的数对应push序列数的下标,如果该下标小于index1,则不存在,如果大于,则继续遍历,直至push队列为空。

import java.util.ArrayList;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
      ArrayList<Integer> list1 = new ArrayList<>();
        for(Integer i: pushA) {
            list1.add(i);
        }

        boolean result = false;

        int i = 0;
        int index1 = 0;
        int index2;
        while(i < popA.length) {
            index2 = list1.indexOf(popA[i]);
            if(index2 < index1) {
                return false;
            }
            list1.remove(index2);
            if(list1.size() == 0) {
                    result = true;
                    break;
                }
            i++;

            if(index2 >= 1) {
                index2--;
                while(index2 >= 0 && list1.get(index2) == popA[i]) {
                    list1.remove(index2);
                    index2--;
                    i++;
                }
                if(list1.size() == 0) {
                    result = true;
                    break;
                }
            }
            index1 = index2;
        }
        return result;
    }
}

22、从上往下打印二叉树

题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
解题思路:用一个ArrayList存放树中的节点,null除外,遍历ArrayList获得子女节点并打印

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<TreeNode> list = new ArrayList<>();
        ArrayList<Integer> result = new ArrayList<>();

        if(root == null) {
            return result;
        }

        result.add(root.val);
        list.add(root);
        for(int i = 0; i < list.size(); i++) {
            if(list.get(i).left != null) {
                list.add(list.get(i).left);
                result.add(list.get(i).left.val);
            }
            if(list.get(i).right != null) {
                list.add(list.get(i).right);
                result.add(list.get(i).right.val);
            }

        }

        return result;
    }
}

23、二叉搜索树的后序遍历序列

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

解题思路:后序遍历,则数组的最后一个数就是这个二叉树的根,根据二叉搜索树的特点,左子树上所有的点都小于根节点,右子树上所有的点都大于根节点。所以 从头 开始遍历数组,直到找到第一个大于等于根的数(如果等于说明该二叉树没有右子树,如果该数是数组的第一个数说明该二叉树没有左子树),则左边的数都是左子树的节点,右边的数都是右子树的节点,两边的最后一个数分别是左右子树的根节点,遍历右子树,如果有小于根节点的,则不是二叉搜索树。再递归判断左右子树是否是二叉搜索树

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence == null) {
             return false;
         }

         int length = sequence.length;

         if(length == 0){
             return false;
         }

         if(length == 1) {
             return true;
         }

         int root = sequence[length - 1];
         int index = 0;
         for(int i = 0; i < length; i++) {
             if(sequence[i] >= root) {
                 index = i;
                 break;
             }
         }

         int[] left = new int[index];
         int[] right = new int[length - 1 - index];

         for(int i = 0; i < index; i++) {
             left[i] = sequence[i];
         }

         for(int i = 0; i < length - 1- index; i++) {
             if(sequence[i + index + 1] < root) {
                 return false;
             }else {
                 right[i] = sequence[index + 1];
             }
         }

         if(left.length == 0) {
             return VerifySquenceOfBST(right);
         }else if(right.length == 0) {
             return VerifySquenceOfBST(left);
         }else {
             return VerifySquenceOfBST(left) && VerifySquenceOfBST(right);
         }

    }
}

24、二叉树中和为某一值的路径

题目描述:输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
解题思路:使用递归解决问题,
如果当前路径的值等于目标值则加入结果集,
如果当前路径的值小于目标值则左递归或右递归继续进行查找
如果当前路径的值大于目标值则回退一个点继续进行查找

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 {
    ArrayList<ArrayList<Integer>> list = new ArrayList<>();
    ArrayList<Integer> path = new ArrayList<>();

    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {

        if(root == null) {
            return list;
        }

        path.add(root.val);

        if(root.left == null && root.right == null && root.val == target) {
            list.add(new ArrayList<>(path));
        }
        if(root.left != null && target > root.val) {
            FindPath(root.left, target - root.val);
        }
        if(root.right != null && target > root.val) {
            FindPath(root.right, target - root.val);
        }

        path.remove(path.size() - 1);
        return list;

    }

}

25、复杂链表的复制

题目描述:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路:1、将原链表的每个节点复制一份,如将A复制为A1,将A1插入到A后
2、添加新增复制节点的random值,如A1.random = A.random.next
3、将原链表中新增的节点拆分出来,得到复制链表

/*
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){
        if(pHead == null) {
            return null;
        }

        RandomListNode current = pHead;

        while(current != null) {
            RandomListNode cloneNode = new RandomListNode(current.label);
            cloneNode.next = current.next;
            current.next = cloneNode;
            current = cloneNode.next;
        }

        current = pHead;
        while(current != null) {
            RandomListNode cloneNode = current.next;

            System.out.println(current.random == null);

            if(current.random != null) {
                cloneNode.random = current.random.next;
                System.out.println("random:" + current.random.next.label);
            }
            current = cloneNode.next;
        }


        current = pHead;
        RandomListNode pCloneHead = pHead.next;

        while(current != null) {
           RandomListNode cloneNode = current.next;
           current.next = cloneNode.next;
           
           if(cloneNode.next != null) {
               cloneNode.next = current.next.next;
           }
           
           current = current.next;
           
        }

        return pCloneHead;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值