leetcode算法题-剑指Offer篇(2)
1、 从尾到头打印链表
1.1 题目描述:
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
1.2 题解
1.2.1 创建数组保存链表节点值,对数组进行反转;
public int[] reversePrint(ListNode head) {
if(head==null)
return new int[0];//如果头结点为空,返回空数组
ListNode index =head;
ArrayList<Integer> list=new ArrayList<>();
while(index!=null){//正向保存节点值
list.add(index.val);
index=index.next;
}
int length=list.size();
int[] result =new int[length];
for(int i=0;i<length;i++){//逆向保存节点值
result[i]=list.get(length-i-1);
}
return result;
}
1.2.2 利用栈的后进先出的性质,来保存节点值,在一一弹出;
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode temp = head;
while (temp != null) {//将节点一一保存到栈中
stack.push(temp);
temp = temp.next;
}
int size = stack.size();
int[] print = new int[size];
for (int i = 0; i < size; i++) {//从栈中一一得出节点值
print[i] = stack.pop().val;
}
return print;
}
2、重建二叉树
2.1 题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
2.2 题解
2.2.1 利用前序遍历和中序遍历的性质
前序遍历的顺序是父节点、左子节点、右子节点;中序遍历的顺序是,左子节点、父节点、右子节点
前序遍历第一个是根节点,由于数字不重复,因此找到中序遍历中等于根节点的值,则此节点的左侧为左子树,右侧为右子树
;以此类推,直到找到前中后序的最后一位;
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0 || preorder == null)
return null;
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();//保存中序遍历的每个元素及其对应的下标
int length=preorder.length;
for (int i = 0; i < length; i++) {
indexMap.put(inorder[i], i);
}
TreeNode root = helpBuildTree(preorder, 0, length - 1, inorder, 0, length - 1, indexMap);
return root;
}
/**
*
* @param preorder 前序遍历
* @param preorderStart 前序遍历开始位置
* @param preorderEnd 前序遍历终止位置
* @param inorder 中序遍历
* @param inorderStart 开始位置
* @param inorderEnd 终止位置
* @param indexMap 保存中序遍历的每个元素及其对应的下标
* @return
*/
public TreeNode helpBuildTree(int[] preorder, int preorderStart, int preorderEnd, int[] inorder, int inorderStart, int inorderEnd, Map<Integer, Integer> indexMap) {
if (preorderStart > preorderEnd) {
return null;
}
int rootVal = preorder[preorderStart];
TreeNode root = new TreeNode(rootVal);
if(preorderStart == preorderEnd)
return root;
else {
int rootIndex = indexMap.get(rootVal);//从map中取出相应值在中序遍历中的下标
int leftNodes = rootIndex - inorderStart, rightNodes = inorderEnd - rootIndex;//父节点的左右分别为左右子树
TreeNode leftSubtree = helpBuildTree(preorder, preorderStart + 1, preorderStart + leftNodes, inorder, inorderStart, rootIndex - 1, indexMap);
TreeNode rightSubtree = helpBuildTree(preorder, preorderEnd - rightNodes + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd, indexMap);
root.left = leftSubtree;
root.right = rightSubtree;
return root;
}
}
3、用两个栈实现队列
3.1 题目描述:
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
3.2 题解
3.2.1
Stack<Integer> appendStack;//放入用
Stack<Integer> deleteStack;//取出用
public CQueue() {
appendStack=new Stack<>();
deleteStack=new Stack<>();
}
public void appendTail(int value) {
appendStack.push(value);
}
public int deleteHead() {
if(deleteStack.empty()&&appendStack.empty())
return -1;
else {
if(deleteStack.empty()){
while(!appendStack.empty())
deleteStack.push(appendStack.pop());//将放入的值存放到取出用栈,因为栈的后进先出,这样能保证取出顺序
return deleteStack.pop();
}
else {
return deleteStack.pop();
}
}
}