算法实践3 查找

问题:

写出两种检索算法:在一个排好序的数组\(T[1\dots n]\)中查找\(x\),如果\(x\)\(T\)中,输出\(x\)\(T\)的下标\(j\);如果\(x\)不在\(T\)中,输出\(j=0\).按实验模板编写,“分析”部分仅给出复杂度结果即可。

解析

因为数组已经排好序了,所以我们可以很容易地对其进行查找。

方法一:二分查找。设起始查找区间为整个区间,左端点为\(1\),右端点为\(n\),每次计算出中间端点的位置。因为数组有序,所以我们可以判断中间端点与\(x\)的值的大小关系,来确定下一个要查找的区间在哪里。每一步都将区间缩小,最终完成查找。

方法二:倍增。假设原数组里存在\(x\),那么\(x\)所在的位置与数组头位置的差值就是个确定值。我们将这个值转换成二进制,从大到小枚举二进制位数。因为原数组有序,所以如果当前位数的值≤\(x\)的话,我们就可以移动到这个位置,来进行下一步查找。最后判断一下我们所在的位置的值是不是\(x\)就行了。如果不存在\(x\)的话,我们会到小于\(x\)值大小,并且最接近\(x\)的位置。

设计

二分

int l = 1, int r = n, int mid;
while (l <= r) {
    mid = 中间端点
    if (mid对应的值为x) return mid;
    if (mid对应的值比x小) {
        l = mid + 1;
    } else {
        r = mid - 1;
    }
}
return 没找到

倍增

int pos = 1;
for (从大到小枚举二进制位数i) {
    if (pos加上值后的位置超过了区间大小) continue;
    if (pos加上值后的位置对应的值小于等于x) 更新pos
}
if (pos对应的值等于x) return pos;
else return 没找到

分析

二分查找每次都把区间缩小一半,时间复杂度\(O(logn)\)

倍增将数字拆成二进制,时间复杂度\(O(logn)\)

源码

https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验3 查找
二分

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const int N = 1e4 + 7;

int a[N], n, x;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    sort(a + 1, a + 1 + n);
    scanf("%d", &x);
    int l = 1, r = n, mid;
	while (l <= r) {
	    mid = l + r >> 1; 
	    if (a[mid] == x) break;
	    if (a[mid] < x) {
	        l = mid + 1;
	    } else {
	        r = mid - 1;
	    }
	}
    if (a[mid] == x) {
        printf("%d\n", mid);
    } else {
        puts("0");
    }
    return 0;
}

倍增

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const int N = 1e4 + 7;

int a[N], n, x;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    scanf("%d", &x);
    int pos = 1;
    for (int i = 14; i >= 0; --i) {
        if (pos + (1 << i) > n) continue;
        if (a[pos + (1 << i)] <= x) {
            pos += 1 << i;
        }
    }
    if (a[pos] == x) {
        printf("%d\n", pos);
    } else {
        puts("0");
    }
    return 0;
}
posted @ 2021-03-29 16:05  stff577  阅读(51)  评论(0)    收藏  举报