阅读 99

算法六 二分查找与二叉排序树(Java实现)

二分查找

二分查找又称折半查找。首先,假设表中元素是按升序排列,将表中间位置的关键字与查找关键字比较:

1.如果两者相等,则查找成功;

2.否则利用中间位置将表分成前、后两个子表:1)如果中间位置的关键字大于查找关键字,则进一步查找前一子表;2)否则进一步查找后一子表。

重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

二叉查找(排序)树

二叉查找树(Binary Search Tree),它是-颗具有下列性质的二叉树:

1.若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值。

2.若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值。

3.左、右子树也分别为二叉排序树。

4.等于的情况只能出现在左子树或右子树中的某一侧。

由于二叉查找树的中序遍历是从小到大的,故又名二叉排序树(Binary Sort Tree)。

二叉查找树插入节点

将某节点(insert node), 插入至以node为根二叉查找树中:

如果insert _node节点值小于当前node节点值:如果node有左子树,则递归的将该节点插入至左子树为根二叉排序树中;否则,将node->left赋值为该节点地址。

否则(大于等于情况): 如果node有右子树,则递归的将该节点插入至右子树为根二叉排序树中;否则,将node->right赋值为该节点地址。

二叉查找树查找数值

查找数值value是否在二叉查找树中出现:

如果value等于当前查看node的节点值:返回真。

如果value节点值小于当前node节点值:如果当前节点有左子树,继续在左子树中查找该值;否则,返回假。

否则(value节点值大于当前node节点值):如果当前节点有右子树,继续在右子树中查找该值;否则,返回假。

1、LeetCode35搜索插入位置

class Solution {     public int searchInsert(int[] nums, int target) {         int index = -1;//最终返回下标         int begin = 0;//搜索区间左端点         int end = nums.length-1;//搜索区间右端点         while(index == -1){             int mid = (begin+end)/2;             if(target == nums[mid]){                 index = mid;             }             else if(target < nums[mid]){                 if(mid == 0||target > nums[mid-1]){                     index = mid;                 }                 end = mid-1;//如果target小于中点,更新区间右端点             }             else if(target > nums[mid]){                 if(mid == nums.length-1||target < nums[mid+1]){                     index = mid+1;                 }                 begin = mid+1;//如果target大于中点,更新区间左端点             }         }         return index;     } } 复制代码

2、LeetCode34在排序数组中查找元素的第一个和最后一个位置

思路:查找区间左端点时,增加如下限制条件:当target == nums[mid]时,若此时mid == 0或nums[mid-1] < target,则说明mid即为区间左端点,返回;否则设置区间右端点为mid-1。查找区间右端点时,增加如下限制条件:当target == nums[mid]时,若此时mid == nums.size()- 1或nums[mid + 1]>target,则说明mid即为区间右端点;否则设置区间左端点为mid + 1。

class Solution {     public int[] searchRange(int[] nums, int target) {         int leftIdx = left_bound(nums, target);         int rightIdx = right_bound(nums, target);         if (leftIdx <= rightIdx && rightIdx < nums.length) {             return new int[]{leftIdx, rightIdx};         }          return new int[]{-1, -1};     }     public int left_bound(int[] nums, int target) {         int left = 0, right = nums.length - 1;         while (left <= right) {             int mid = (left + right) / 2;             if (target == nums[mid]){                 if (mid == 0||nums[mid-1] < target){                     return mid;                 }                 right = mid - 1;             } else if (nums[mid] > target) {                 right = mid - 1;             } else if (nums[mid] < target){                 left = mid + 1;             }         }         return -1;     }     public int right_bound(int[] nums, int target) {         int left = 0, right = nums.length - 1;         while (left <= right) {             int mid = (left + right) / 2;             if (target == nums[mid]){                 if (mid == nums.length - 1||nums[mid+1] > target){                     return mid;                 }                 left = mid + 1;             } else if (nums[mid] > target) {                 right = mid - 1;             } else if (nums[mid] < target){                 left = mid + 1;             }         }         return -1;     } } 复制代码

3、LeetCode33搜索旋转排序数组

思路:nums[begin]>nums[end]

image.png

image.png

class Solution {     public int search(int[] nums, int target) {         int begin = 0,end = nums.length-1;         while(begin <= end){             int mid = (begin+end)/2;             if(target == nums[mid]){                 return mid;             }             else if(target < nums[mid]){                 if(nums[begin] < nums[mid]){                     if(target >= nums[begin]){                         end = mid-1;                     }else{                         begin = mid+1;                     }                 }else if(nums[begin] > nums[mid]){                     end = mid-1;                 }else if(nums[begin] == nums[mid]){                     begin = mid+1;                 }             }             else if(target > nums[mid]){                 if(nums[begin] < nums[mid]){                     begin = mid+1;                 }else if(nums[begin] > nums[mid]){                     if(target >= nums[begin]){                         end = mid-1;                     }else{                         begin = mid+1;                     }                 }else if(nums[begin] == nums[mid]){                     begin = mid+1;                 }             }         }         return -1;     } } 复制代码

leetcode官方题解

class Solution {     public int search(int[] nums, int target) {         int n = nums.length;         if (n == 0) {             return -1;         }         if (n == 1) {             return nums[0] == target ? 0 : -1;         }         int l = 0, r = n - 1;         while (l <= r) {             int mid = (l + r) / 2;             if (nums[mid] == target) {                 return mid;             }             if (nums[0] <= nums[mid]) {                 if (nums[0] <= target && target < nums[mid]) {                     r = mid - 1;                 } else {                     l = mid + 1;                 }             } else {                 if (nums[mid] < target && target <= nums[n - 1]) {                     l = mid + 1;                 } else {                     r = mid - 1;                 }             }         }         return -1;     } } 复制代码

4、LeetCode449序列化和反序列化二叉搜索树

思路:二叉查找树编码为字符串:将二叉查找树前序遍历,遍历时将整型的数据转为字符串,并将这些字符串数据进行连接,连接时使用特殊符号分隔。

将字符串解码为二叉查找树:将字符串按照编码时的分隔符”#”,将各个数字逐个拆分出来,将第一个数字构建为二叉查找树的根节点,后面各个数字构建出的节点按解析时的顺序插入根节点中,返回根节点,即完成了解码工作。

LeetCode评论代码

/**  * Definition for a binary tree node.  * public class TreeNode {  *     int val;  *     TreeNode left;  *     TreeNode right;  *     TreeNode(int x) { val = x; }  * }  */ public class Codec {     // Encodes a tree to a single string.     public String serialize(TreeNode root) {         if (root == null) {             return "";         }         StringBuilder sb = new StringBuilder();         BST_preorder(root, sb);//将root指向的树转为字符串sb         return sb.substring(0, sb.length() -1);     }     // 前序遍历二叉排序树,将root.val转换为字符串存储至sb     private void BST_preorder(TreeNode root, StringBuilder sb) {         if (root == null) {             return;         }         sb.append(root.val).append("#");         BST_preorder(root.left, sb);         BST_preorder(root.right, sb);     }     // Decodes your encoded data to tree.     public TreeNode deserialize(String data) {          if (data.isEmpty()) {             return null;         }         String[] split = data.split("#");         return buildTreeNode(split, 0, split.length -1);     }     private static TreeNode buildTreeNode(String[] split, int left, int right) {         if (left > right) {             return null;         }         TreeNode root = new TreeNode(Integer.parseInt(split[left]));         int index = right + 1;         for (int i = left + 1; i <= right; i++) {             if (Integer.parseInt(split[i]) > root.val) {                 index = i;                 break;             }         }         root.left = buildTreeNode(split, left + 1, index -1);         root.right = buildTreeNode(split, index, right);         return root;     } } // Your Codec object will be instantiated and called as such: // Codec ser = new Codec(); // Codec deser = new Codec(); // String tree = ser.serialize(root); // TreeNode ans = deser.deserialize(tree); // return ans;


作者:zust_Isabella
链接:https://juejin.cn/post/7002129809568595998


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐