算法通关村第九关|白银|二分查找与搜索树高频问题【持续更新】

1.基于二分查找的拓展问题

1.1 山脉数组的峰顶索引

原题:力扣852.

给定一个数组,索引 i 左边的数依次递增,右边的数依次递减, i 处的数最大,求 i 是多少。

可以直接遍历,但是用二分法的速度更快,对于二分的某个位置 mid ,mid 可能有三种情况:

1 mid 在上升阶段:arr[mid]>arr[mid - 1] && arr[mid]

2 mid 在峰顶:arr[mid]>arr[mid-1] && arr[mid]>arr[mid+1]

3 mid 在下降阶段:arr[mid]arr[mid+1]

因此可以判断出哪个 mid 是处于峰顶。

public int peakIndexInMountainArray(int[] arr) {
	if (arr.length == 3) {
        return 1;
    }
    int left = 1, right = arr.length - 2;
    while (left < right) {
        int mid = left + ((right - left) >> 1);
        if (arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]) {
            return mid;
        }
        if (arr[mid] < arr[mid + 1] && arr[mid] > arr[mid - 1]) {
            left = mid + 1;
        }
        if (arr[mid] > arr[mid + 1] && arr[mid] < arr[mid - 1]) {
            right = mid - 1;
        }
    }
	return left;
}

1.2 寻找旋转排序数组中的最小数字

原题:力扣153.

定义 low 为 0 ,high 为 length-1 ,pivot 为中间值,pivot 大于 low 说明在最小值的左侧,pivot 需要向右移动。 pivot 小于 high 说明在最小值的右侧或者就是最小值, high 需要向左移动 。

public int findMin(int[] nums) {
	int low = 0,
    int high = nums.length - 1;
    while (low < high) {
        int pivot = low + ((high - low) >> 1);
        if (nums[pivot] < nums[high]) {
            high = pivot;
        } else {
            low = pivot + 1;
        }
    }
    return nums[low];
}

1.3 找缺失数字

在长度为 n-1 的递增排序数组中,有不重复的从 0 到 n-1 的 n-1 个数字,其中的一个数字不在数组中,找出那个数字。

在缺失的数字前,nums[i] == i,在缺失的数字后,nums[i] != i 。因此,使用二分查找找到第一个 nums[i] != i 即可。如果找不到符合条件的下标,说明缺失的数字是 n 。

public int missingNumber(int[] a) {
	int left = 0;
    int right = a.length - 1;
    while (left < right) {
        int mid = right + ((left - right) >> 1);
        if (a[mid] == mid) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

1.4 优化求平方根

如果 x 没有平方根,就向下取整。

public int sqrt(int x) {
	int l = 1, r = x;
	while (l <= r) {
    	int mid = l + ((r - l) >> 1);
        if (x / mid > mid) {
            l = mid + 1;
        } else if (x / mid < mid) {
            r = mid - 1;
        } else if (x / mid == mid) {
            return mid;
        }
    }
	return r;
}

2.中序与搜索树原理

因为中序和前后序的一些性质不同,之前的好多题目都是使用前序和后序以及层次遍历去解决,但是中序也是有用的,中序可以和搜索树结合在一起,但是前后序就不能和搜索树结合。

二叉搜索树:按照中序遍历,序列是一个递增序列。

因为左子树不为空,则左子树上所有结点的值都要小于根节点值,右子树不为空则所有结点的值都大于根节点值,对于子树,也同样得是二叉搜索树。

搜索树是有序的,所以可以根据一些条件让递归停止执行,也叫剪枝。

2.1 二叉搜索树中搜索特定值

原题:力扣700.

采用递归实现:

public TreeNode searchBST(TreeNode root, int val) {
	if (root == null || val == root.val) {
        return root;
    }
    return val < root.val ? searchBST(root.left, val) : searchBST(root.right, val);
}

采用迭代实现:

public TreeNode searchBST(TreeNode root, int val) {
	while (root != null && val != root.val) {
        root = val < root.val ? root.left, root.right;
    }
    return root;
}

2.2 验证二叉搜索树

原题:力扣98.

给定一个二叉树的根节点,判断是否是一个有效的二叉搜索树。

因为对一个二叉搜索树来说,按照中序遍历,序列是一个递增序列。所以使用中序遍历给定的根节点,看是否是递增序列就可以知道是不是有效的二叉搜索树。

long pre = Long.MIN_VALUE;// 用long的最小值是因为int的最小值会被覆盖到
public boolean isValidBST(TreeNode root) {
	if (root == null) {
        return true;
	}
	if (!isValidBST(root.left)) {
        return false;
    }
	if (root.val <= pre) {
        return false;
    }
	pre = root.val;
	return isValidBST(root.right);
}

2.3 二叉搜索树的最小绝对差

【持续更新】

2.4 二叉搜索树的众数

【持续更新】

如果对您有帮助,请点赞关注支持我,谢谢!❤
如有错误或者不足之处,敬请指正!❤
个人主页:星不易 ❤
算法通关村专栏:不易|算法通关村 ❤

你可能感兴趣的:(不易,算法通关村,算法,java,算法通关村)