你未必出类拔萃,但一定与众不同
剑指offer
题7 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof
二叉树的前序遍历 根左右 第一个数字是树的根节点的值
中序遍历 左根右 根节点的值在序列的中间
后序遍历 左右根 根节点的值在序列的最后
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || preorder.length == 0){
return null;
}
if(inorder == null || inorder.length == 0){
return null;
}
TreeNode tree = build(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
return tree;
}
public TreeNode build(int[] preorder,int preorderLeft,int preorderRight,
int[] inorder,int inorderLeft,int inorderRight){
if(preorderLeft > preorderRight || inorderLeft > inorderRight){
return null;
}
TreeNode root = new TreeNode(preorder[preorderLeft]);
for (int i = inorderLeft; i <=inorderRight; i++) {
if(preorder[preorderLeft] == inorder[i]){
//对左子树的 前序遍历和中序遍历进行切割
root.left = build(preorder,preorderLeft + 1,preorderLeft+ (i - inorderLeft),inorder,inorderLeft,i-1);
//对右子树的前序遍历和中序遍历进行切割
root.right =build(preorder,i-inorderLeft + preorderLeft+ 1,preorderRight,inorder,i+1,inorderRight);
}
}
return root;
}
}
题8 二叉树的下一个节点
给定一颗二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点。
public static Node getNext(Node pNode){
if(pNode == null){
return null;
}
Node pNext = null;
//先判断当前节点的右子树是否为空 为空就直接返回
if(pNode.right != null){
//拿到当前节点的右子树
Node pRight = pNode.right;
//判断当前右子树的左子树 因为是中序遍历的下一个节点
while(pRight.left != null){
pRight = pRight.left;
}
pNext = pRight;
}
return pNext;
}
题9 两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
链接:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof
class CQueue {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public CQueue() {
}
public void appendTail(int value) {
stack1.push(value);
}
public int deleteHead() {
int temp = 0;
//两个栈都为空 则数据为空
if (stack1.isEmpty() && stack2.isEmpty())
{
return -1;
}
//第一个栈不为空 第二个栈为空 则需要把第一个栈的元素一个一个出栈 再入栈到第二个栈中
//比如 第一个栈中从上到下 为 3 2 1 出栈时 3先出栈再入栈到第二个栈中的栈底 然后是2 1 刚好顺序反转
if (!stack1.empty() && stack2.empty())
{
while (!stack1.empty())
{
stack2.push(stack1.peek());
stack1.pop();
}
temp = stack2.peek();
stack2.pop();
return temp;
}
//第二个栈不为空 则说明所有栈中元素都在第二个栈 直接出栈即可
if (!stack2.empty())
{
temp = stack2.peek();
stack2.pop();
return temp;
}
return temp;
}
}
题10 斐波那契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof
思路:有点像跳楼梯,直接创建一个数组为n+1的大小,n下标的值用来存储最终值
然后采用for循环的模式 挨个求解 第n-1下标的数据
class Solution {
public int fib(int n) {
if(n == 0){
return 0;
}
int[] number = new int[n+1];
number[0] = 0;
number[1] = 1;
int sum = 0;
for (int i = 2; i < number.length; i++) {
number[i] = number[i-1] + number[i-2];
number[i] =number[i] % 1000000007;
}
return number[n];
}
}
题11旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2]
为 [1,2,3,4,5]
的一个旋转,该数组的最小值为1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof
思路:采用双指针,因为是部分有序的数组,让左指针向右移动,右指针不动,则左指针第一次碰到比右指针小的则为最小
public int minArray(int[] numbers) {
if(numbers.length == 0){
return 0;
}
int left = 0;
int right = numbers.length -1;
while(left < right){
if(numbers[left] >= numbers[right]){
left++;
}
if(numbers[left] < numbers[right]){
return numbers[left];
}
}
return numbers[left];
}