- 菜鸟也能看懂的重建二叉树 看两天看会了 手还不会 发现自己没有把想法转变为代码的能力
- 发现自己太拖延了 实验结果一直拖着没写 不知道为啥 可能是对自己的信心不大把
package offer;
import java.util.HashMap;
//重建二叉树
//递归的方法 先写出口后写递归式
class Solution {
//哈希表存值跟位置 标记中序的位置
HashMap<Integer, Integer> map = new HashMap<>();
//保存先序遍历
int[] preorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
//把中序的数值都放进哈希表里
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return recur(0, 0, inorder.length - 1);
}
//当前根的的索引
//递归树的左边界,即数组左边界
//递归树的右边界,即数组右边界
private TreeNode recur(int pre_root, int in_left, int in_right) {
//递归出口调用
if (in_left > in_right)
return null;
//获取root节点 在前序里面
TreeNode root = new TreeNode(preorder[pre_root]);
//获取在中序遍历中根节点所在索引,以方便获取左子树的数量
int index = map.get(preorder[pre_root]);
//左子树的根的索引为先序中的根节点+1
//递归左子树的左边界为原来的中序in_left
//递归右子树的右边界为中序中的根节点索引-1
root.left = recur(pre_root + 1, in_left, index - 1);
root.right = recur(pre_root + (index - in_left) + 1, index + 1, in_right);
return root;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
}
public class Test8 {
//把构建的数递归先序遍历出来
public static void preorderDfs(TreeNode root) {
if (root == null)
return;
System.out.println(root.val);
preorderDfs(root.left);
preorderDfs(root.right);
}
public static void main(String[] args) {
int[] preorder = {3, 9, 20, 15, 7};
int[] inorder = {9, 3, 15, 20, 7};
//递归输出先序
Solution s = new Solution();
TreeNode tree = s.buildTree(preorder, inorder);
preorderDfs(tree);
}
}
- 旋转数组最小值
回忆折半查找
package offer;
//二分查找变种 原来数组都是有序的数组
//薪给的数组不是有序的 要找出 不是有序的左右边
//找出旋转点
// 先实现二分查找 递归不递归
public class Test9 {
//递归的写法
public static int recursionBinarySearch(int[] array, int key, int low, int high) {
//先写出口
if (key < array[low] || key > array[high] || low > high)
return -1;
int mid = (low + high) / 2;
if (array[mid] > key)
//中间数值大于关键字 则关键字在左边
//位置要是mid-1
return recursionBinarySearch(array, key, low, mid - 1);
else if (array[mid] < key)
//mid+1 过了中间这个位置
return recursionBinarySearch(array, key, mid + 1, high);
else return mid;
}
//非递归的写法
public static int recursionBinarySearch2(int[] array, int key) {
//把每一个数值都写好定义 初始化为0
int low = 0;
int high = array.length - 1;
int mid = 0;
if (key < array[low] || key > array[high] || low > high)
return -1;
while (low <= high) {
//每次查找一个中间值
mid = (low + high) / 2;
//在左边
if (array[mid] > key)
high = mid - 1;
//在右边
else if (array[mid] < key) {
low = mid + 1;
} else return mid;
}
return -1;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9, 11};
int key = 9;
//判断没有的情况
int position = recursionBinarySearch(arr, 9, 0, arr.length - 1);
int position2 = recursionBinarySearch2(arr, 4);
if (position == -1 || position2 == -1) {
System.out.println("没有查找到");
} else {
System.out.println(position);
System.out.println(position2);
}
}
}
改进折半查找进行旋转数组最小值
package offer;
//旋转数组最小值 找旋转接点
//二分查找是有序的 查找异常值
//注意 while (low < high) 多等于号会跳转不出来
public class Test10 {
public static int minArray(int[] array) {
//初始化用到的指标
int low = 0;
int high = array.length - 1;
int mid = 0;
while (low < high) {
mid = (high + low) / 2;
//[3,4,5,1,2]
//找到节点的异常值
//最小值在右边
if (array[mid] > array[high])
low = mid + 1;
[4,5,6,7,7,7]
else if (array[mid] < array[high]) {
//看mid是不是异常值
high = mid;
}
//[1,0,1,1,1] [1,1,1,0,1]
else {//从左到右遍历查看
findMin(array, low, high);
}
}
return array[low];
}
public static int findMin(int[] numbers, int low, int high) {
int result = numbers[low];
for (int i = 0; i <= high; i++) {
if (numbers[i] < result)
result = numbers[i];
}
return result;
}
public static void main(String[] args) {
int[] array = {3, 4, 5, 1, 2};
System.out.println(minArray(array));
}
}