题目来源于CSDN每日一练2023年3月15日期!
题目描述:
A地跟B地的网络中间有n个节点(不包括A地和B地),相邻的两个节点是通过网线连接。正常的情况下,A地和B地是可以连通的,有一天,A地和B地突然不连通了,已知只有一段网线出问题(两个相邻的节点)小明需要排查哪段网线出问题。他的排查步骤是: 1。 选择某个中间节点 2。 在这个节点上判断跟A地B地是否连通,用来判断那一边出问题 请问小明最少要排查多少次,才能保证一定可以找到故障网线
输入描述:
一个正整数 n (n <= 10^18),表示A地和B地之间的节点数
输出描述:
输出一个数字,代表保证一定可以找到故障网线的前提下,小明最少要排查多少次
原题图片:
题目分析:
二分查找或者二分法。
假设 A 到 B 的距离为 d,已知出了问题的那个节点在距离 A 的位置为 x(0 <= x <= d),那么问题就变成了如何确定 x。我们可以采用二分法的思想,首先在节点的中心点进行测试,如果中心点与 A 的连通性没有变化,那么问题就出在右侧,否则问题就在左侧。然后依次类推,每次都将待查找的区间缩小一半,直到找到问题节点。
因此,我们可以用一个 while 循环来实现二分查找
程序C语言:
#include <stdio.h> int main() { long long n; scanf("%lld", &n); long long left = 0, right = n; long long mid; long long ans = 0; while (left <= right) { mid = (left + right) / 2; ans++; if ((mid * (n - mid + 1) + mid * (mid - 1) / 2) >= n) { right = mid - 1; } else { left = mid + 1; } } printf("%lld\n", ans); return 0; }
程序解读:
在代码中,我们首先读入节点数 n,然后初始化待查找区间的左右端点 left 和 right。接下来,我们使用一个 while 循环,每次计算区间的中心点 mid,并测试 mid 节点与 A 是否连通。如果 mid 节点与 A 连通,说明问题节点在 mid 的左侧,因此将 right 设为 mid - 1;否则问题节点在 mid 的右侧,将 left 设为 mid + 1。在循环的过程中,我们使用一个计数器 ans 记录了需要测试的次数,最终输出 ans 即可。
需要注意的是,题目中节点数 n 的范围非常大,因此需要使用 long long 类型来存储。同时,在计算 mid 节点的时候,为了避免整数溢出,我们采用了 mid = (left + right) / 2 的方式,而没有使用 mid = left + (right - left) / 2。
运行结果: