二分算法另向理解

本文讨论了如何在未排序的数组中使用二分查找算法,即使目标值可能出现在二分点中。通过最多两次交换操作,确保算法能正确找到目标值并输出操作次数和下标。
摘要由CSDN通过智能技术生成

本篇文章创作灵感来源:Code Force round 935 E 题

题目大致分析

题目说二分算法前提是已经排好了顺序,但是幕墙给你一个没有排好序的数组,然后让你从这个数组中用二分找到一个目标数,这自然很有可能办不到,于是让你从这个数组中执行最多两次操作,每一次操作都是选择两个下标,并且交换着两个下表所对应的数组内容使二分查找能够成功地查找到目标值。

背后本质

本质就是二分算法实际上所依靠的只有那几个二分点,他依靠着二分点与目标值大小之间的比较,简单的判断,目标值在此时二分点的左边还是右边,这也是排序的意义所在,确保目标值比二分点小的时候就一定在二分点的左边,大的时候就一定在二分点右边。
此时虽然没有排序,但是经过题目保证,最多只需要两次操作,也就是说,唔,值得深思,当初看这里就觉得很可疑。
后来发现
只要目标值不曾在二分点中出现过,那么目标值真正所在的位置在哪里,好像都不影响对一个无序数组二分求目标数字二分到最后锁定的位置
既然如此,问题大致分为一下两种情况

1.目标值不曾在二分点中出现过:那么只需要像往常一下二分,二分到最后得到一个位置下标,最后交换目标值所在位置(可暴力找到),然后输出操作一次,并输出这两个下标。
2.目标值曾经在二分点中出现过,那么,只需要把目标值移动到第一个位置,这样继续二分下去虽然有可能跟原来数组最终得到的位置不同,不过不重要,我只需要知道最终二分会到哪一个位置,然后把那个位置与1交换就可以。

总结

二分算法最终结果只与目标值以及所有二分中点有关。

代码实现

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define For for(int i=1;i<=n;i++)
#define rFor for(int i=n;i>0;i--)
#define rep(i, sta, end) for(int i=sta;i<=end;i++)
#define ALL(x) for(auto item:x)

inline void solve() {
    int n, x;
    cin >> n >> x;
    vector<int> arr(n + 10);
    For cin >> arr[i];
    int pos = 0;
    For {
        if (arr[i] == x)
            pos = i;
    }
    swap(arr[pos], arr[1]);
    int l = 1, r = n + 1;
    while (l < r - 1) {
        int mid = (l + r) >> 1;
        if (arr[mid] <= arr[1])
            l = mid;
        else r = mid;
    }
    int ans = l;
    cout << 2 << endl;
    cout << pos << " " << 1 << endl;
    cout << 1 << " " << ans << endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int num = 1;
    cin >> num;
    while (num--)
        solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值