本专栏目录
蓝桥杯算法竞赛大纲
数论相关(Java)
枚举相关(Java)
对象排序(Java)
字符串相关(Java)
排序相关算法(Java)
记忆化搜索(Java)
树论相关(Java)
图论相关(Java)
堆(Java)
贪心(Java)
文章目录
- 二叉搜索树
- 二叉搜索树的结构AC1
- 二叉搜索树的结构AC2
- 前中后层序遍历
- 是否完全二叉搜索树
- 完全二叉树的层序遍历
- 玩转二叉树
- 线段树
- 线段树LazyTag
- AVLTree
- ST表
- 公共祖先问题
- 构建BST的两种方式和构建AVL的一种方式
二叉搜索树
package 树论;
import java.util.Scanner;
public class _二叉搜索树 {
static int n;
static int[] arr;
static int c1=0,c2=0;
static boolean flag1=false,flag2=false;
public static void main(String[] args) {
// 给定一个整数键值序列,现请你编写程序,
// 判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
arr = new int[n];
Node root = null;
for (int i = 0; i < n; i++) {
int x = scan.nextInt();
arr[i] = x;
root = insert(root, x);
}
preOrder(root);
if (!flag1){
System.out.println("YES");
postOrder(root);
return;
}
preMirrOrder(root);
if (!flag2){
System.out.println("YES");
postMirrOrder(root);
return;
}
System.out.println("NO");
}
// 后序镜像遍历
static boolean f2 = false;
public static void postMirrOrder(Node root) {
if (root.r!=null) postMirrOrder(root.r);
if (root.l!=null) postMirrOrder(root.l);
if (!f2){
System.out.print(root.data);
f2 = true;
}else {
System.out.print(" " + root.data);
}
}
// 前序镜像遍历 + 验证
public static void preMirrOrder(Node root) {
if (flag2 || arr[c2++]!=root.data){
flag2 = true;
return;
}
if (root.r!=null) preMirrOrder(root.r);
if (root.l!=null) preMirrOrder(root.l);
}
// 后序遍历
static boolean f1 = false;
public static void postOrder(Node root) {
if (root.l!=null) postOrder(root.l);
if (root.r!=null) postOrder(root.r);
if (!f1){
System.out.print(root.data);
f1 = true;
}else {
System.out.print(" " + root.data);
}
}
// 前序遍历 + 验证
public static void preOrder(Node root) {
if (flag1 || arr[c1++]!=root.data){
flag1 = true;
return;
}
if (root.l!=null){
preOrder(root.l);
}
if (root.r!=null){
preOrder(root.r);
}
}
// 构建二叉搜索树(BST)
public static Node insert(Node root, int x) {
if (root == null){
root = new Node();
root.data = x;
return root;
}
if (x < root.data){
root.l = insert(root.l, x);
}else {
root.r = insert(root.r, x);
}
return root;
}
static class Node{
Node l,r;
int data;
}
}
二叉搜索树的结构AC1
package 树论;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class _二叉搜索树的结构AC1 {
static int n,m;
static Map<Integer, Integer> layers = new HashMap<>(); // 层数
static Map<Integer, Integer> par = new HashMap<>(); // 父节点
static Map<Integer, Integer> lor = new HashMap<>(); // 左0还是右1子树
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
Node root = new Node();
for (int i = 0; i < n; i++) {
int x = scan.nextInt();
insert(root, x, 0);
}
m = scan.nextInt();
scan.nextLine();
for (int i = 0; i < m; i++) {
String line = scan.nextLine();
String[] strArr = line.split(" ");
if (line.contains("root")){
int x = Integer.parseInt(strArr[0]);
if (isExit(x) && x == root.data){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("siblings")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[2]);
if (par.get(a)!=null&&par.get(b)!=null&&par.get(a)-par.get(b)==0){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("level")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[2]);
if (isExit(a)&&isExit(b)&&layers.get(a)-layers.get(b)==0){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("parent")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[5]);
if (isExit(a)&&par.get(b)!=null&&par.get(b)-a==0){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("left")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[6]);
if (par.get(a)!=null&&isExit(b)&&par.get(a)-b==0&&lor.get(a)==0){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("right")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[6]);
if (par.get(a)!=null&&isExit(b)&&par.get(a)-b==0&&lor.get(a)==1){
System.out.println("Yes");
}else {
System.out.println("No");
}
}
}
}
public static boolean isExit(int x){
if (layers.get(x)==null){
return false;
}
return true;
}
static boolean flag = false;
public static void insert(Node root, int x, int layer){
if (!flag){
flag = true;
root.data = x;
layers.put(root.data,1);
return;
}
if (x<root.data){
if (root.l==null){
root.l = new Node();
root.l.data = x;
par.put(x, root.data);
layers.put(x, layer);
lor.put(x, 0);
return;
}
insert(root.l, x, layer+1);
}else {
if (root.r==null){
root.r = new Node();
root.r.data = x;
par.put(x, root.data);
layers.put(x, layer);
lor.put(x, 1);
return;
}
insert(root.r, x, layer+1);
}
}
static class Node{
Node r,l;
int data=-1;
}
}
二叉搜索树的结构AC2
package 树论;
import java.util.Scanner;
public class _二叉搜索树的结构AC2 {
static int n,m;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
Node root = new Node();
for (int i = 0; i < n; i++) {
int x = scan.nextInt();
insert(root, x, 1);
}
m = scan.nextInt();
scan.nextLine();
for (int i = 0; i < m; i++) {
String line = scan.nextLine();
String[] strArr = line.split(" ");
if (line.contains("root")){
int x = Integer.parseInt(strArr[0]);
if (x == root.data){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("siblings")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[2]);
Node na = find(root,a);
Node nb = find(root,b);
if (na!=null&&nb!=null&&na.parent!=null&&nb.parent!=null&&nb.parent==na.parent){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("level")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[2]);
Node na = find(root,a);
Node nb = find(root,b);
if (na!=null&&nb!=null&&na.depth==nb.depth){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("parent")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[5]);
Node na = find(root,a);
Node nb = find(root,b);
if (na!=null&&nb!=null&&nb.parent==na){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("left")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[6]);
Node na = find(root,a);
Node nb = find(root,b);
if (na!=null&&nb!=null&&nb.l==na){
System.out.println("Yes");
}else {
System.out.println("No");
}
}else if (line.contains("right")){
int a = Integer.parseInt(strArr[0]);
int b = Integer.parseInt(strArr[6]);
Node na = find(root,a);
Node nb = find(root,b);
if (na!=null&&nb!=null&&nb.r==na){
System.out.println("Yes");
}else {
System.out.println("No");
}
}
}
}
public static Node find(Node root, int x){
if (root==null) return null;
if (x == root.data) return root;
if (x < root.data){
return find(root.l,x);
}else {
return find(root.r, x);
}
}
static boolean flag = false;
public static void insert(Node root, int x, int layer){
if (!flag){
flag = true;
root.data = x;
root.depth = 0;
root.parent = null;
return;
}
if (x<root.data){
if (root.l==null){
root.l = new Node();
root.l.data = x;
root.l.parent = root;
root.l.depth = layer;
return;
}
insert(root.l, x, layer+1);
}else {
if (root.r==null){
root.r = new Node();
root.r.data = x;
root.r.parent = root;
root.r.depth = layer;
return;
}
insert(root.r, x, layer+1);
}
}
static class Node{
Node r,l,parent;
int data,depth;
}
}
前中后层序遍历
package 树论;
import java.util.Scanner;
public class _前中后层序遍历 {
static int n;
static int[] postArr;
static int[] midArr;
public static void main(String[] args) {
// 给定一棵二叉树的后序遍历和中序遍历,输出其层序遍历的序列
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
postArr = new int[n+1];
midArr = new int[n+1];
for (int i = 1; i <= n; i++) {
postArr[i] = scan.nextInt();
}
for (int i = 1; i <= n; i++) {
midArr[i] = scan.nextInt();
}
Node root = buildTree(1,n,1,n);
levelOrder(root);
}
// 树的层序遍历
private static void levelOrder(Node root) {
Node[] Q = new Node[n];
int front = -1;
int rear = -1;
Q[++rear] = root;
while (front!=rear){
Node node = Q[++front];
if (node==root) System.out.print(node.data);
else System.out.print(" " + node.data);
if (node.l != null) Q[++rear] = node.l;
if (node.r != null) Q[++rear] = node.r;
}
}
public static Node buildTree(int m1, int e1, int m2, int e2){
if (m1 > e1 || m2 > e2){
return null;
}
// 后序遍历的最后一个元素是根
int x = postArr[e1];
Node root = new Node();
root.data = x;
// 在中序遍历中查找root
for (int i = m2; i <= e2; i++) {
if (midArr[i]==x){
//左子树长度
int k = i - m2;
root.l = buildTree(m1,m1+k-1,m2,i-1);
root.r = buildTree(m1+k,e1-1,i+1,e2);
break;
}
}
return root;
}
static class Node{
Node r,l;
int data;
}
}
是否完全二叉搜索树
package 树论;
import java.util.Scanner;
public class _是否完全二叉搜索树 {
static int n;
static int max = 0;
public static void main(String[] args) {
// 将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),
// 你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
Node root = null;
for (int i = 0; i < n; i++) {
int x = scan.nextInt();
root = insert(root, x);
}
levelOrder(root);
System.out.println();
dfs(root, 1);
if (max == n) System.out.println("YES");
else System.out.println("NO");
}
public static void dfs(Node root, int v){
if (v>max) max = v;
if (root.l!=null) dfs(root.l, v*2);
if (root.r!=null) dfs(root.r, v*2+1);
}
public static void levelOrder(Node root) {
Node[] Q = new Node[n];
int front = -1;
int rear = -1;
Q[++rear] = root;
boolean flag = true;
while (front!=rear){
Node node = Q[++front];
if (flag){
System.out.print(node.data);
flag = false;
}else {
System.out.print(" " + node.data);
}
if (node.l!=null) Q[++rear] = node.l;
if (node.r!=null) Q[++rear] = node.r;
}
}
public static Node insert(Node root, int x) {
if (root == null){
root = new Node();
root.data = x;
return root;
}
if (x > root.data){
root.l = insert(root.l, x);
}else {
root.r = insert(root.r, x);
}
return root;
}
static class Node{
Node r,l;
int data;
}
}
完全二叉树的层序遍历
package 树论;
import java.util.Scanner;
public class _完全二叉树的层序遍历 {
static int n;
static int[] arr;
static int[] brr;
static int c = 1;
public static void main(String[] args) {
// 给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
arr = new int[n+1];
brr = new int[n+1];
for (int i = 1; i <= n; i++) {
arr[i] = scan.nextInt();
}
postOrder(1);
System.out.print(brr[1]);
for (int i = 2; i <= n; i++) {
System.out.print(" " + brr[i]);
}
}
public static void postOrder(int v) {
if (v>n){
return;
}
postOrder(v*2);
postOrder(v*2 + 1);
brr[v] = arr[c++];
}
}
玩转二叉树
package 树论;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class _玩转二叉树 {
static int[] midArr;
static int[] preArr;
static int n;
static boolean flag = false;
static class Node{
Node l;
Node r;
int data;
}
public static void main(String[] args) {
// 给定一棵二叉树的中序遍历和前序遍历,
// 请你先将树做个镜面反转,再输出反转后的层序遍历的序列。
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
midArr = new int[n+1];
preArr = new int[n+1];
for (int i = 1; i <= n; i++) {
midArr[i] = scan.nextInt();
}
for (int i = 1; i <= n; i++) {
preArr[i] = scan.nextInt();
}
Node root = fn(1,n,1,n);
levelOrder(root);
}
private static void levelOrder(Node root) {
List<Node> ls = new ArrayList<>();
ls.add(root);
while (!ls.isEmpty()){
Node node = ls.remove(0);
if (!flag){
flag = true;
System.out.print(node.data);
}else {
System.out.print(" " + node.data);
}
if (node.l!=null) ls.add(node.l);
if (node.r!=null) ls.add(node.r);
}
}
private static Node fn(int preS, int preE, int midS, int midE) {
if (preS>preE || midS>midE){
return null;
}
int x = preArr[preS];
Node root = new Node();
root.data = x;
for (int i = midS; i <= midE; i++) {
if (midArr[i]==x){
int k = i - midS; // 左子树长度
// 镜像构造
root.r = fn(preS+1,preS+k, midS, i-1);
root.l = fn(preS+k+1,preE, i+1, midE);
}
}
return root;
}
}
线段树
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iN0MDNyYWYkZDN5ATZ4UjYyYzX1IjMxgTM0IzLcZDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
package 树论;
public class _线段树 {
static int[] arr = {1, 3, 5, 7, 9, 11};
static int[] tree = new int[1000005];
static int n = 6;
public static void main(String[] args) {
buildTree(0, 0, n-1);
for (int i = 0; i <= 14; i++) {
System.out.print(tree[i] + " ");
}
System.out.println();
updateTree(0, 0, n-1, 4, 6);
for (int i = 0; i <= 14; i++) {
System.out.print(tree[i] + " ");
}
System.out.println();
// 查找原数组中索引为[2, 5] 区间的和
int sum = queryTree(0, 0, n-1, 2, 5);
System.out.println(sum);
}
/**
* 区间查询合
* @param node tree中的下标
* @param start arr数组中的下标
* @param end
* @param L 带查询的区间是[L, R]
* @param R
* @return
*/
private static int queryTree(int node, int start, int end, int L, int R) {
if (end < L || start > R){ // 如果[L, R] 和 [start, end] 没有交集
return 0;
}else if (L<=start && R >= end){ // 如果 [L, R] 区间包含 [start, end]
return tree[node];
}else if (start==end){ // 如果查找单点则直接返回值
return tree[node];
}
int mid = (start + end) / 2;
int left_node = node * 2 + 1;
int right_node = node * 2 + 2;
int sum_left = queryTree(left_node, start, mid, L, R);
int sum_right = queryTree(right_node, mid+1, end, L, R);
return sum_left + sum_right;
}
// 单点更新 arr[idx] = val
public static void updateTree(int node, int start, int end, int idx, int val){
if (start==end){
// 当查找到单点时,更新
tree[node] = val;
arr[idx] = val;
return;
}
int mid = (start + end) / 2;
int left_node = node * 2 + 1;
int right_node = left_node + 1;
if (idx <= mid){ // 如果idx在arr的左边,则在tree的左子树查找更新
updateTree(left_node, start, mid, idx, val);
}else {
updateTree(right_node, mid+1, end, idx, val);
}
// 更新父节点
tree[node] = tree[left_node] + tree[right_node];
}
/**
*
* @param node tree中的下标
* @param start arr中的下标 表示区间 [start, end]
* @param end
*/
public static void buildTree(int node, int start, int end){
if (start==end){
tree[node] = arr[start];
return;
}
int mid = (start + end) / 2;
// tree中子树下标
int left_node = 2 * node + 1;
int right_node = left_node + 1;
// 分别建左右子树
buildTree(left_node, start, mid);
buildTree(right_node, mid+1, end);
tree[node] = tree[left_node] + tree[right_node];
}
}
线段树LazyTag
package 树论;
import java.util.Scanner;
// http://poj.org/problem?id=3468
public class _线段树LazyTag {
static long[] tree;
static long[] tags;
static long[] nums;
static int n, m;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
nums = new long[n+1];
tree = new long[4*n+1];
tags = new long[4*n+1];
for (int i = 1; i <= n; i++) {
nums[i] = scan.nextInt();
}
buildTree(0, 1, n);
for (int i = 0; i < m; i++) {
String s = scan.next();
if (s.equals("Q")){
int L = scan.nextInt();
int R = scan.nextInt();
long sum = query(0, 1, n, L, R);
System.out.println(sum);
}else {
int L = scan.nextInt();
int R = scan.nextInt();
int val = scan.nextInt();
updateTree(0, 1, n, L, R, val);
}
}
}
public static void buildTree(int node, int start, int end){
if (start==end){
tree[node] = nums[start];
return;
}
int mid = (start + end) / 2;
int left_node = node * 2 + 1;
int right_node = node * 2 + 2;
buildTree(left_node, start, mid);
buildTree(right_node, mid+1, end);
pushUP(node);
}
public static long query(int node, int start, int end, int L, int R) {
if (L<=start && end <= R){
return tree[node];
}else if (L>end || R < start){
return 0;
}else if (start==end){
return tree[node];
}
// 下放后才能查询
if (tags[node]!=0){
pushDown(node, start, end);
}
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
long sum_left = query(left_node, start, mid, L, R);
long sum_right = query(right_node, mid+1, end, L, R);
return sum_left + sum_right;
}
public static void updateTree(int node, int start, int end, int L, int R, int val) {
if (L <= start && end <= R){
// 如果[start,end] 在待查询的区间 [L, R] 内, 则进行LazyTag标记后返回
tree[node] += (end - start + 1) * val;
tags[node] += val;
return;
}
// 更新前如果当前节点有LazyTag标记,则先下放
if (tags[node]!=0){
pushDown(node, start, end);
}
int mid = (start + end) / 2;
int left_node = node * 2 + 1;
int right_node = node * 2 + 2;
// [L, R] 和 [start, mid] 有交集, 则去左边更新
if (L <= mid){
updateTree(left_node, start, mid, L, R, val);
}
// [L, R] 和 [mid + 1, end] 有交集, 则去右边更新
if (mid + 1 <=R){
updateTree(right_node, mid+1, end, L, R, val);
}
// 更新节点的值
pushUP(node);
}
// 根据父节点的LazyTag标记,更新子节点的值,并且给子节点打标记
public static void pushDown(int idx, int start, int end){
long val = tags[idx];
int mid = (start + end) / 2;
int left_node = idx * 2 + 1;
int right_node = idx * 2 + 2;
tree[left_node] += (mid - start + 1) * val;
tree[right_node] += (end - (mid + 1) + 1) * val;
tags[left_node] += val;
tags[right_node] += val;
tags[idx] = 0;
}
// 根据子节点的值更新父节点的值
public static void pushUP(int idx){
tree[idx] = tree[idx*2+1] + tree[idx*2+2];
}
}
AVLTree
package 树论;
import java.util.Scanner;
public class _AVLTree {
static class Node{
int data;
Node left,right;
}
static int n;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
Node root = null;
for (int i = 0; i < n; i++) {
int x = scan.nextInt();
root = insert(root, x);
}
levelOrder(root);
}
public static void levelOrder(Node root){
Node[] Q = new Node[n];
int rear = -1;
int front = -1;
Q[++rear] = root;
while (rear!=front){
Node node = Q[++front];
System.out.print(node.data + " ");
if (node.left!=null) {
Q[++rear] = node.left;
}
if (node.right!=null) {
Q[++rear] = node.right;
}
}
}
public static Node rotateRightLeft(Node root){
root.right = rotateRight(root.right);
root = rotateLeft(root);
return root;
}
public static Node rotateLeftRight(Node root){
root.left = rotateLeft(root.left);
root = rotateRight(root);
return root;
}
public static Node rotateLeft(Node root){ // 左旋
Node right = root.right;
root.right = right.left;
right.left = root;
return right;
}
public static Node rotateRight(Node root){ // 右旋
Node left = root.left;
root.left = left.right;
left.right = root;
return left;
}
public static int getHeight(Node root){
if (root==null) return 0;
return Math.max(getHeight(root.left), getHeight(root.right)) + 1;
}
// 构建AVL
public static Node insert(Node root, int x){
if (root == null){
root = new Node();
root.data = x;
return root;
}
if (x < root.data){
root.left = insert(root.left, x);
if (getHeight(root.left)-getHeight(root.right)>=2){
// 如果高度差是因为x插入了左子树的右子树造成的,则左右旋
if (x > root.left.data){
root = rotateLeftRight(root);
}else { // 否则只右旋
root = rotateRight(root);
}
}
}else {
root.right = insert(root.right, x);
if (getHeight(root.right)-getHeight(root.left)>=2){
// 如果高度差是因为x插入了右子树的左子树造成的,则右左旋
if (x<root.right.data){
root = rotateRightLeft(root);
}else { // 否则只左旋
root = rotateLeft(root);
}
}
}
return root;
}
}
ST表
package 树论;
import java.util.Scanner;
public class _ST表 {
static int n,m;
static int[][] dp; // dp[i][j] 表示区间 [i, i+2^j-1], 即下标从i开始,长度为2^j的区间
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
dp = new int[n][(int)Math.log(n)+5];
// 预处理
for (int i = 0; i < n; i++) {
dp[i][0] = scan.nextInt();
}
for (int j = 1; j <= Math.log(n); j++) {
for (int i = 0; i + (1 << j) - 1 < n; i++) {
// 长度一半的两个相邻区间的最大/最小值
dp[i][j] = Math.min(dp[i][j-1], dp[i + (1 << (j - 1))][j-1]);
}
}
int l, r;
for (int i = 0; i < m; i++) {
l = scan.nextInt();
r = scan.nextInt();
if (i==m-1){
System.out.print(query(l-1, r-1));
}else {
System.out.print(query(l-1, r-1) + " ");
}
}
}
public static int query(int l, int r) {
// 待求的区间长度
int len = r - l + 1;
int j = (int)Math.log(len);
// max/min([l, l+2^j-1], [r-2^j+1, r])
return Math.min(dp[l][j], dp[r - (1 << j) + 1][j]);
}
}
公共祖先问题
static class Node{
Node r,l,parent;
int data,depth;
}
增加一个parent字段,然后查找到后反搜标记,最后看是否有重复标记的
并查集有可能也可以解决
构建BST的两种方式和构建AVL的一种方式
BST
(一) 一般用于公共父节点问题
static boolean flag = false;
public static void insert(Node root, int x, int layer){
if (!flag){
flag = true;
root.data = x;
root.depth = 0;
root.parent = null;
return;
}
if (x<root.data){
if (root.l==null){
root.l = new Node();
root.l.data = x;
root.l.parent = root;
root.l.depth = layer;
return;
}
insert(root.l, x, layer+1);
}else {
if (root.r==null){
root.r = new Node();
root.r.data = x;
root.r.parent = root;
root.r.depth = layer;
return;
}
insert(root.r, x, layer+1);
}
}
(二)
public static Node insert(Node root, int x) {
if (root == null){
root = new Node();
root.data = x;
return root;
}
if (x < root.data){
root.l = insert(root.l, x);
}else {
root.r = insert(root.r, x);
}
return root;
}
AVL
// 构建AVL
public static Node insert(Node root, int x){
if (root == null){
root = new Node();
root.data = x;
return root;
}
if (x < root.data){
root.left = insert(root.left, x);
if (getHeight(root.left)-getHeight(root.right)>=2){
// 如果高度差是因为x插入了左子树的右子树造成的,则左右旋
if (x > root.left.data){
root = rotateLeftRight(root);
}else { // 否则只右旋
root = rotateRight(root);
}
}
}else {
root.right = insert(root.right, x);
if (getHeight(root.right)-getHeight(root.left)>=2){
// 如果高度差是因为x插入了右子树的左子树造成的,则右左旋
if (x<root.right.data){
root = rotateRightLeft(root);
}else { // 否则只左旋
root = rotateLeft(root);
}
}
}
return root;
}