剑指Offer题目JAVA版思路与代码(二)

第四题:重建二叉树
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:
这个题目考的是二叉树遍历相关的知识点。二叉树常见的遍历方式有三种,分别是前中后序。前序的遍历顺序是:根节点-左子树-右子树;中序的遍历顺序是:左子树-根子树-右子树。
所以这个题目中前序序列的第一个数字就是根节点的值,对应到中序便利的序列中就可以知道4,7,2这三个树字是左子树,1是根节点,5,3,8,6是右子树。然后用同样的方式去解析左子树和右子树。
代码:

import java.util.Arrays;
/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode head = null;
        if (pre.length == 0 || in.length == 0 || pre.length != in.length) {
            return head;
        }
        head = new TreeNode(pre[0]);
        int index = 0;
        while (in[index] != pre[0]) {
            index ++; //找到在中序序列中根节点的index
        }
        if (index == 0) {
            head.left = null;
        }else {
            head.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, index+1), Arrays.copyOfRange(in, 0, index));
        }
        if (index == pre.length-1) {
            head.right = null;
        }else {
            head.right = reConstructBinaryTree(Arrays.copyOfRange(pre, index+1, pre.length), Arrays.copyOfRange(in, index+1, in.length));
        }
        return head;
    }
}

第五题:用两个栈实现队列
题目描述:
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:
这一题考的是对两种数据结构的理解。栈的特点是:先进后出,而队列的特点是:先进先出。题目的意思是要用两个先进后出的栈来实现先进先出的队列的特点。
我们可以想象下,当我们连续把好几个数都存入栈中,我们要怎么才能获得最先存入栈中的第一个数呢?解决的办法就是把第一个栈中的所有数字再依次pop出来,然后push到第二个栈中,这样,之前在栈底的数就到了栈顶。
于是我们可以定义第一个栈为存入栈,第二个栈为取出栈,push的时候就只往存入栈中存,pop的时候就要去判断取出栈是否为空了,如果为空,则去把存入栈的数全push到取出栈中,再取出即可。
代码:

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }

    public int pop() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        if (stack2.isEmpty()) {
            return -1;
        }
        return stack2.pop();
    }
}

第六题:旋转数组的最小数字
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:
此题考查的是二分查找,并不难,但是要注意的几点是:

  1. 先应该判断数组首元素与数组的尾元素的大小,如果首元素小于尾元素,很显然,返回首元素即可;
  2. 当首元素,尾元素,中间元素三者相等,此时应该顺序遍历找到最小元素,因为这样无法判断最小元素是在前半段还是后半段;
  3. 循环退出的条件是首指针与尾指针相邻。

代码:

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int[] array) {
        if (array == null || array.length == 0) {
            return 0;
        }
        int index1 = 0;
        int index2 = array.length - 1;
        int mid = index1;
        while (array[index1] >= array[index2]) {
            if (index2 == index1 + 1) {// 前指针与后指针相邻
                mid = index2;
                break;
            }
            mid = (index1 + index2) / 2;
            if (array[mid] == array[index1] && array[mid] == array[index2]) {// 首尾中三者相同
                return MinInOrder(array, index1, index2);
            }
            if (array[mid] >= array[index1]) {// 中 大于 首
                index1 = mid;
            } else {// 中 小于 首
                index2 = mid;
            }
        }
        return array[mid];
    }

    public int MinInOrder(int[] array, int index1, int index2) {
        int ret = array[index1];
        for (int i = index1; i < index2; i++) {
            if (array[i] <= ret) {
                ret = array[i];
            }
        }
        return ret;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值