二分算法 openjudge 百练 python

https://www.icourse163.org/learn/PKU-1001894005?tid=1450413466#/learn/content
程序设计与算法(二)算法基础

4143:和为给定数

# 4143:和为给定数
# http://bailian.openjudge.cn/practice/4143


# 二分查找的目标是对于有序列表,在其中寻找指定的目标元素的位置。
def BinarySearch(L, target):
    left = 0
    right = len(L) - 1
    while (left <= right):
        mid = left + (right - left) // 2  # 为了防止(L+ R)过大溢出
        if (L[mid] == target):  # 如果中间位置的元素 == target,那么查找成功
            return mid
        elif (L[mid] < target):  # 如果中间位置的元素 < target,那么左端点设置为中间+1
            left = mid + 1
        else:  # 如果中间位置的元素 > target,那么右端点设置为中间-1
            right = mid - 1
    return 'TARGET_NOT_FOUND'


num_int = int(input())  # 第一行是整数n(0 < n <= 100,000),表示有n个整数。
int_list = input().split()  # 第二行是n个整数。整数的范围是在0到10^8之间。
for i in range(0, len(int_list)):
    int_list[i] = int(int_list[i])
sumsum = int(input())  # 第三行是一个整数m(0 <= m <= 2^30),表示需要得到的和。

# 方法1:排序 + 二分查找
# 1)将数组排序,复杂度是O(n*log(n))
# 2)对数组中的每个元素a[i],在数组中二分查找m-a[i],看能否找到。
# 复杂度log(n), 最坏要查找n-2次,
# 所以查找这部分的复杂度也是O(n*log(n))
# 这种解法总的复杂度是O(n*log(n))的。

int_list.sort()

for ii in range(0, num_int):
    ind = BinarySearch(int_list, sumsum - int_list[ii])
    if ind != 'TARGET_NOT_FOUND':
        print('%d %d' % (int_list[ii], int_list[ind]))
        break
if ind == 'TARGET_NOT_FOUND':
    print('No')
# 4143:和为给定数
# http://bailian.openjudge.cn/practice/4143

num_int = int(input())  # 第一行是整数n(0 < n <= 100,000),表示有n个整数。
int_list = input().split()  # 第二行是n个整数。整数的范围是在0到10^8之间。
for i in range(0, len(int_list)):
    int_list[i] = int(int_list[i])
sumsum = int(input())  # 第三行是一个整数m(0 <= m <= 2^30),表示需要得到的和。

# 方法2:排序 + 查找
# 1)将数组排序,复杂度是O(n*log(n))
# 2)查找的时候,设置两个变量i和j,i初值是0,j初值是n-1
# 如果a[i]+a[j]大于m,就让j减1
# 如果a[i]+a[j]小于m,就让加1
# 直至a[i]+a[j]=m。
# 这种解法总的复杂度是O(n*log(n))的。

int_list.sort()

left = 0
right = num_int - 1
while left != right:
    if int_list[left] + int_list[right] > sumsum:
        right -= 1
    elif int_list[left] + int_list[right] < sumsum:
        left += 1
    else:
        print('%d %d' % (int_list[left], int_list[right]))
        break
if left == right:
    print('No')

2456:Aggressive cows 疯牛

# 2456:Aggressive cows
# http://bailian.openjudge.cn/practice/2456

# 判断能否以距离mid将C头牛全部分配到房间列表room_list中
def Check(mid, room_list, C):
    count = 1
    temp = room_list[0] # 将第一头牛分配给房间列表的第0个房间
    for ii in range(1, len(room_list)):  # 从最小编号的隔间开始分配房间
        if room_list[ii] - temp >= mid:  # 如果第ii个房间与房间temp的距离 >= mid 
            count += 1 # 对已经分配了的牛进行计数
            temp = room_list[ii] # 分配第ii个房间
            if count >= C:  # 如果分配完了C头牛
                return True
    return False


# (2)二分查找 在L中求满足Check(mid, L, C)的最大的距离mid
# 在[L,R]内用二分法尝试“最大最近距离”mid = (L+ R)/2 (L,R初值为[1, 1,000,000,000/C]
# 复杂度log(1,000,000,000/C) * N
def BinarySearch(room_list, C):
    left = 0  #最小距离
    right = room_list[-1] - room_list[0]  # 最大距离
    while (left <= right):  # 最后一次循环结束后,left = right + 1
        mid = left + (right - left) // 2  # 为了防止(L+ R)过大溢出
        if Check(mid, room_list, C):  # 若mid可行,则记住该mid,然后在新[L,R]中继续尝试(L= mid+1)
            left = mid + 1
        else:  # 若mid不可行,则在新[L, R]中继续尝试(R= mid-1)
            right = mid - 1
    # 若最后一次循环中mid满足条件,则left = mid + 1 = right + 1,最大的满足条件的应该是mid = left-1
    # 若最后一次循环中mid不满足条件,则right = mid - 1 = left - 1,最大的满足条件的应该是mid-1 =left-1
    return left - 1


room_list = input().split()  # 第1行:空格分隔的两个整数N和C。
N = int(room_list[0])  # N个隔间 N == len(room_list)
C = int(room_list[1])  # C头牛
room_list = []
for ii in range(0, N):  # 第2~N+1行:分别指出xi的位置。
    room_list.append(int(input()))

room_list.sort()  # 对隔间的编号由小到大排序
print("%d" % BinarySearch(room_list, C))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzz的学习笔记本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值