剑指offer(04-06)题解

04题解–重建二叉树

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路解析

这里我们首先需要知道前序遍历和中序遍历的规则
前序遍历(根左右)
中序遍历(左根右)
我们是通过前序序列的第一个节点来划分中序序列,从而找到该节点的左右子树,之后只需要在对相应的序列做递归操作即可。
这里面我们只要注意一下Arrays.copyOfRange(,,)这个函数是左闭右开的就行了

源代码

import java.util.Arrays;
public class Solution {
	    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
	        if(pre.length==0||in.length==0)
	        	return null;
	        TreeNode treeNode=new TreeNode(pre[0]);
	        for(int i=0;i<in.length;i++)
	        {
	        	if(in[i]==treeNode.val)
	        	{
	        		treeNode.left=reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));//左子树重建
	        		treeNode.right=reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, pre.length), Arrays.copyOfRange(in,i+1,in.length));//右子树重建
	        	}
	        }
	        return treeNode;
	    }
	}

05题解–用两个栈实现队列

题目描述

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路解析

这里面我们需要懂栈和队列的特性
栈:先进后出
队列:先进先出
通过下面的图来进行讲解
这是栈:
在这里插入图片描述

这是队列:
在这里插入图片描述
我们的处理逻辑,主要存储还是通过一个栈来实现,但是需要另外一个栈来充当中间件的功能:
在这里插入图片描述

源代码

import java.util.Stack;

public class Solution {
    static Stack<Integer> stack1 = new Stack<Integer>();
	 static Stack<Integer> stack2 = new Stack<Integer>(); 
	 public static void push(int node) {
	     stack1.push(node); 
	 }
	 public static int pop() {
		stack2.clear();//首先保证stack2中是没有任何元素的
		int node;
	    if(stack1==null)//避免栈为空时,pop报错
	    	return (Integer) null;
	    else 
	    {
	    	while(!stack1.empty())
	    	{
	    		stack2.push(stack1.pop());
	    	}
	    	node=stack2.pop();
	    	while (!stack2.empty()) {
	    		stack1.push(stack2.pop());
			}	
	    	return node;
	    }
	 }
}

06题解–旋转数组的最小数字

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

思路解析

最简单的方法就是通过暴力来解决,也能通过,但是显然这是不可取的。
主要还是通过二分法来进行,但是这又和我们平常的二分有所不同,他的顺序是部分有序但是二分的整体思想还是能够用的,
二分主要的就是怎么比较,和谁比较。
这里我们采取的是和右端点进行比较。
首先必须明白一点,给我们的数组一定是这样的形式
【{升序数组1},{升序数组2}】 中间有一处是断开的,正是因为他翻转的因素。
现在我们举例说明
第一种情况就是mid<last
举例 {4,5,1,2,3},既然mid<last,那么就可以确定mid-last必定是处于升序的数组之中,这里大家可以通过反证法即可验证。那么显然mid+1~last的元素肯定是大于mid的,所以区间范围就处于0-mid之中,这里因为mid可能刚好是最小的那个元素,所以必须将mid这个位置也包括进去。
第二种情况就是mid>last
举例{3,4,5,1,2},既然mid>last,那么就可以确定0-mid必定是处于升序的数组之中,这里大家也可以通过反证法即可验证。那么显然0-mid的元素都是大于last的,所以区间就确定在了mid+1~last之间了,这里因为mid本身就已经大于last了,所以必定不是最小的元素了,所以排除。
第三种情况就是mid=last
这里面稍微比较复杂,因为=并不能确定我们到底是处于哪一区间的数组之中,所以我们只能慢慢地减少数组中的元素。
举两个例子
{1,2,0,0,0} 这种情况最小值是落在了右边的区间上。
{4,1,2,2,2} 这种情况最小值是落在了左边的区间上。
所以显然我们并不能通过上述的方法进行大幅度的区间减少,只能通过last-1的方式来减少区间范围。

源代码

import java.util.Arrays;
public class Solution {
    public static int minNumberInRotateArray(int [] array) {
		if(array.length==0) return 0;//这是在空数组时进行输出
		if(array.length==1) return array[0];//因为在最后的递归过程中,到最后剩下一个元素时,其实就应该输出了。否则再次进入递归过程那么,就会陷入数组为空的情况,那样就会直接输出0了
		//注意边界的取值情况
		int first=0;
		int last=array.length-1;
		int mid=(last-first)/2;
		//同时注意Arrays.copyOfRange(,,)这个函数是左闭右开的就行了
		if(array[mid]<array[last])
		{
			return minNumberInRotateArray(Arrays.copyOfRange(array,first,mid+1));
		}
		else if(array[mid]>array[last])
		{
			return minNumberInRotateArray(Arrays.copyOfRange(array,mid+1,last+1));
		}
		else 
		{
			return minNumberInRotateArray(Arrays.copyOfRange(array,first,last));
		}
    }
}

看到最后了如果可以的话可以关注一下博主的b站号,新人up需要你的支持。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lovely__RR/article/details/107782319