大厂真题:【模拟】阿里蚂蚁2023秋招-讨厌鬼的区间

题目描述与示例
题目描述
讨厌鬼有一个数x,他每次操作可以令x = x + 1或x = x - 1
讨厌鬼还有两个区间[l1, r1]和[l2, r2],讨厌鬼想知道,令x同时满足以下条件的最小操作数是多少?

  1. l1 ≤ x ≤ r1,且x是2的倍数
  2. l2 ≤ x ≤ r2,且x是3的倍数
    请输出这个操作数

输入描述
一行输入五个整数x, l1, r1, l2, r2
1 ≤ x ≤ 10^12
1 ≤ l1 ≤ r1 ≤ 10^12
1 ≤ l2 ≤ r2 ≤ 10^12

输出描述
一行一个整数,表示最小操作数。若不存在这样的操作,输出-1。

示例一
输入
5 4 6 1 9
输出
1
说明
+1把5变成6,满足2个条件

示例二
输入
2 2 4 2 8
输出
-1

时空限制
时间限制: C/C++ 1000MS,其他语言 2000MS
内存限制: C/C++ 256M,其他语言 512M

解题思路
条件转换
数据范围很大,考虑O(1)复杂度的算法。
经过若干次操作之后,x需要同时落在区间[l1, r1]和[l2, r2]中,令l = max(l1, l2),r = min(r1, r2),该条件转化为x最终需要落入区间[l, r]中。
x还需要同时是2和3的倍数,由于2和3互质,故该条件转化为x最终需要是6的倍数。
因此题目可以转化为,在区间[l, r]中找到一个距离x最近的一个6的倍数,这个数和x的差的绝对值就是所求的最小操作数。

分类讨论
在区间[l, r]中找到一个距离x最近的一个6的倍数,一共存在3种情况

  1. x在区间[l, r]左边,即x < l
  2. x在区间[l, r]右边,即x > r
  3. x在区间[l, r]之间,即l <= x <= r

对于情况一,我们需要找到大于等于l的第一个6的倍数a,可以用如下方式得到
a = l + ((6 - l % 6) % 6)
对于情况二,我们需要找到小于等于r的第一个6的倍数b,可以用如下方式得到
b = r - r % 6

  • 如果存在a > b,说明区间[l, r]实际上并不包含任何6的倍数,返回-1
  • 如果是第一种情况,x落在l的左边,那么a是[l, r]中距离x最近的6的倍数,返回a-x
  • 如果是第二种情况,x落在r的右边,那么b是[l, r]中距离x最近的6的倍数,返回x-b
    if a > b:
    return -1
    elif x < l:
    return a-x
    elif x > r:
    return x-b

对于情况三,我们需要找到第一个小于等于x的6的倍数xa以及第一个大于等于x的6的倍数xb。可以用类似于求a和b的方法求得。即
xa = x - x % 6
xb = x + ((6 - x % 6) % 6)
对于xa和xb,也要分别讨论与l和r之间的大小关系,查询xa和xb是否落在区间[l, r]中。

  • 如果xa落在l的左边,则xb是距离x最近的6的倍数,返回xb-x
  • 如果xb落在r的右边,则xa是距离x最近的6的倍数,返回x-xa
  • 如果xa和xb均落在[l,r]中,那么选距离更近的作为答案,返回min(x-xa, xb-x)
    if xa < l:
    return xb-x
    elif xb > r:
    return x-xa
    else:
    return min(x-xa, xb-x)

代码
Python

题目:【模拟】阿里蚂蚁2023秋招-讨厌鬼的区间

作者:闭着眼睛学数理化

算法:模拟/数学

代码有看不懂的地方请直接在群上提问

def help(x, l, r):
# a是大于等于l的第一个6的倍数
a = l + ((6 - l % 6) % 6)
# b是小于等于r的第一个6的倍数
b = r - r % 6

# 如果a大于b,说明区间中不包含6的倍数,返回-1
if a > b:
    return -1
# 以下条件语句中,区间[l, r]中一定包含6的倍数
# 第一种情况,x落在l左边,a是答案
elif x < l:
    return a-x
# 第二种情况,x落在r的右边,b是答案
elif x > r:
    return x-b
# 第三种情况,x落在区间[l,r]之间
else:
    # 需要计算,比x小的第一个6的倍数xa和比x大的第一个6的倍数xb
    xa = x - x % 6
    xb = x + ((6 - x % 6) % 6)
    # 如果xa落在l的左边,则xb是距离x最近的6的倍数
    if xa < l:
        return xb-x
    # 如果xb落在r的右边,则xa是距离x最近的6的倍数
    elif xb > r:
        return x-xa
    else:
    # 如果xa和xb均落在[l,r]中,那么选距离更近的作为答案
        return min(x-xa, xb-x)

输入5个参数

x, l1, r1, l2, r2 = map(int, input().split())

分别获得l和r

l = max(l1, l2)
r = min(r1, r2)

如果r小于l,那么区间不存在,直接输出-1

if r < l:
print(-1)

否则则调用help计算结果

else:
ans = help(x, l, r)
print(ans)
Java

C++

时空复杂度
时间复杂度:O(1)。
空间复杂度:O(1)。

华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(算法,数学建模,动态规划)