《剑指Offer》
- 牛客网 20到40题
-
- 面试题21:栈的压人弹出序列
- 面试题22:由上向下打印二叉树 广度优先遍历****
- 面试题23:二叉搜索树的后序遍历
- 面试题24:二叉树中和为某一值的路径 ****
- 面试题25:复杂链表的复制 ****
- 面试题26:二叉搜索树与双向链表
- 面试题27:字符串的排序 **** ------递归
- 面试题28:数组中出现超过次数一半的数字
- 面试题29:最小的K个数
- 面试题30:连续子数组的最大和
- 面试题31:整数中1出现的次数 ***
- 面试题32:把数组排成最小的数
- 面试题33:丑数
- 面试题34:第一个只出现一次的字符
- 面试题35:数组中的逆序对
- 面试题36:两个链表的第一个公共结点
- 面试题37:数字在排序数组中的次数
- 面试题38:二叉树的深度
- 面试题39:判断是否为平衡二叉树 ****
- 面试题40:数组中只出现一次的数字
牛客网 20到40题
面试题21:栈的压人弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路:借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
遇到的问题:在while出栈循环中,发现当循环出栈到j = 4,data_pushA已空时,还会调用peek(),因此抛出EmptyException()。所以我加上了一句,如果data_pushA为空,break;
代码:运行时间:17ms 占用内存:9384k
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA == null||popA == null) return false;
if(pushA.length != popA.length) return false;
Stack data_pushA = new Stack();
int length = pushA.length;
int j = 0;
for(int i = 0;i<length;i++)
{
data_pushA.push(pushA[i]);
if((int)data_pushA.peek() == popA[j]) //如果发现栈顶指针等于出栈的序列的某个值
{
while((int)data_pushA.peek() == popA[j])
{
data_pushA.pop();
j++;
if(data_pushA.isEmpty()) break;
}
}
}
return data_pushA.isEmpty();
}
}
面试题22:由上向下打印二叉树 广度优先遍历****
题目:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
思路:使用两个队列一个存放节点,一个存放值。先将根节点加入到队列中,然后遍历队列中的元素,遍历过程中,访问该元素的左右节点,再将左右子节点加入到队列中来。
遇到的问题:我广度优先遍历新建一个二叉树,利用ArrayList,虽然代码量少,循环的上下界很容易错,调试了1小时。广度优先遍历精髓:一个for循环,i<arrayList.size(),在不断遍历当前结点的时候,如果有左子树,将左子树存入arrayList中,有右子树存入arrayList。循环中每次去TreeNode = arrayList.get(i); i++。巧妙就巧妙在,虽然只用了一个arrayList,但是for()循环遍历整个二叉树,每循环一次,都将当前结点的左右子树(若有)存放到arrayList中,因此arrayList的size()是一个动态增加的过程,arrayList(i++)就是二叉树的每一层从左到右。
public class Task22 {
public TreeNode newTree(int[]array) //按广度优先新建树
{
ArrayList<TreeNode> treeNodes = new ArrayList<>();
TreeNode root = new TreeNode(array[0]);
treeNodes.add(root);
for(int i = 0; i< array.length;i++)
{
TreeNode node = new TreeNode(array[i]);
treeNodes.add(node);
}
for(int i = 1; i<= array.length/2;i++)
{
treeNodes.get(i).left = treeNodes.get(2*i);
treeNodes.get(i).right = treeNodes.get(2*i+1);
}
return treeNodes.get(1);
}
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
ArrayList<Integer> deque = new ArrayList<Integer>();
if(root == null)
{
return deque;
}
list.add(root);
for(int i = 0;i<list.size();i++)
{
TreeNode node = list.get(i);
if(node.left != null)
{
list.add(node.left);
}
if(node.right != null)
{
list.add(node.right);
}
deque.add(node.val);
}
return deque;
}
public static void main(String[] args) {
Task22 task22 = new Task22();
int [] array = {
10,6,14,4,8,12,16};
TreeNode root = task22.newTree(array);
ArrayList<Integer> deque = task22.PrintFromTopToBottom(root);
for(Integer i:deque)
System.out.println(i);
}
}
面试题23:二叉搜索树的后序遍历
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
思路:注意:需要先知道的:二叉搜索树后序遍历,最右一个为根结点root,左子树值都比root小,右子树值都比root大。
代码:能不用递归就尽量不用递归,根据二叉树后序遍历得的结果的特点运行时间:15ms 占用内存:9252k
注意: 一维数组判断是否为空1、array null 判断指针 2、array.length == 0;判断长度是否为空
public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
if(sequence == null) return false;
if(sequence.length == 0) return false;
if(sequence.length <2) return true;
int length = sequence.length - 1;
int root = 0,i = 0;
while(length>=0)
{
root = sequence[length];
while(sequence[i]<root) i++;
while(sequence[i]>root) i++;
if(i<length -1) return false;
length --;
i = 0;
}
return true;
}
}
面试题24:二叉树中和为某一值的路径 ****
题目:输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值