顺序查找
直接从头到尾遍历一遍就行,没啥好说的
public int sequentialSearch(int[] nums,int target) {
for (int i = 0; i < nums.length; i++) {
if(nums[i]==target)return i;
}
return -1;
}
二分查找(折半查找)
二分查找也叫折半查找,是一种高效的查找方法。时间复杂度O(n),但是要注意的是只有顺序存储的有序列表可以使用二分查找。
- 原理
二分查找顾名思义是将列表分为两边。假设列表从小到大排列,首先判断中间位置是否等于查找元素,相等就返回当前位置。大于查找元素就对前半部分列表重复上述操作,小于查找元素就对后半部分列表重复上述操作。
举个栗子:list:[0,1,2,3,4,5,6,7,8,9],target:5,也就是说我们要在列表中寻找值等于5的元素所在的位置。定义两个指针b=0,e=list.length-1一个指向列表开头,一个指向列表末尾。定义mid=(b+e)/2将数组分为两半
*表示b和e,&表示mid
* & *
[0,1,2,3,4,5,6,7,8,9]
list[mid](4)<target(5),因此target必定在mid的右边b=mid+1
⬇
* & *
[0,1,2,3,4,5,6,7,8,9]
list[mid](7)>target(5),因此target必定在mid的左边e=mid-1
⬇
&
* *
[0,1,2,3,4,5,6,7,8,9]
list[mid](5)=target(5),返回mid
如果b>e,也就是头指针大于尾指针了那说明列表中没有target,返回-1;
- 代码实现
//常规写法
public int binarySearch(int[] nums,int target) {
int b=0,e=nums.length-1;
while(b<=e){
int mid=(b+e)/2;
if(nums[mid]==target) return mid;
if(nums[mid]<target){
b=mid+1;
}
if(nums[mid]>target){
e=mid-1;
}
}
return -1;
}
//递归写法
public int binarySearch(int[] nums,int target,int b,int e) {
if(b>e) return -1;
int mid=(b+e)/2;
if(nums[mid]<target)return binarySearch(nums,target,mid+1,e);
if(nums[mid]>target)return binarySearch(nums,target,b,mid-1);
else return mid;
}
分块查找
分块查找综合了顺序查找和二分查找。首先将元数据分为几个块(block)。块于块之间有序,块内的元素无序。然后先使用二分查找确定目标元素在哪个块中,之后再这个块中使用顺序查找最终确定元素的位置。
public int blockSearch(int target) {
int a = binarySearch(max, 0, max.size()-1, target);
if(a==-1)return a;
int end = a == index.size() - 1 ? nums.length-1 : index.get(a + 1);
for (int i = index.get(a); i <=end; i++) {
if (nums[i] == target) {
return i;
}
}
return -1;
}
public int binarySearch(List<Integer> max, int bg, int end, int target) {
if(bg<0||end>=max.size()){
return -1;
}
int mid = (bg + end) / 2;
if(max.get(mid)==target)return mid;
if (mid == max.size() - 1) {
if (target < max.get(mid)&&target>max.get(mid-1)) {
return mid;
}
}
if (mid == 0){
if (target > max.get(mid)&&target<max.get(mid+1)) {
return mid+1;
}else if(target<max.get(mid))return mid;
}
if (max.get(mid) < target) {
if (max.get(mid + 1) > target)
return mid+1;
else {
return binarySearch(max, mid + 1, end, target);
}
}
if (max.get(mid) > target) {
if (max.get(mid - 1) < target)
return mid;
else {
return binarySearch(max, bg, mid - 1, target);
}
}
return -1;
}
二叉搜索树查找
二叉搜索树有一个特性
- 右子树的值大于等于根结点
- 左子树的值小于根结点
- 左右子树都是二叉搜索树
因此在查找二叉搜索树中查找元素时只要判断下于根节点的大小即可,大的往右子树找,小的往左子树找。
时间复杂度完全有序的情况下是O(n),平衡的情况下是O(logn)
package base.searchAlgorithm;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public class SearchBST {
public TreeNode searchBST(TreeNode root, int val) {
while (root != null) {
if (root.val == val)
return root;
else if (root.val > val)
root = root.left;
else if (root.val < val)
root = root.right;
}
return root;
}
}
TODO
- 顺序查找
- 二分查找
- 分块查找
- 二叉搜索树查找