最小差距

28 篇文章 0 订阅
7 篇文章 0 订阅
题目描述

  给定一些不同的一位数字,你可以从这些数字中选择若干个,并将它们按一定顺序排列,组成一个整数,把剩下的数字按一定顺序排列,组成另一个整数。组成的整数不能以0开头(除非这个整数只有1位)。
  例如,给定6个数字,0,1,2,4,6,7,你可以用它们组成一对数10和2467,当然,还可以组成其他的很多对数,比如210和764,204和176。这些对数中两个数差的绝对值最小的是204和176,为28。
  给定N个不同的0~9之间的数字,请你求出用这些数字组成的每对数中,差的绝对值最小的一对(或多对)数的绝对值是多少?

输入数据

  第一行包括一个数 T (T≤1000),为测试数据的组数。
  每组数据包括两行,第一行为一个数 N (2≤N≤10),表示数字的个数。下面一行为 N 个不同的一位数字。

输出数据

  T行,每行一个数,表示第 i 个数据的答案。即最小的差的绝对值。

样例输入
2
6
0 1 2 4 6 7
4
1 6 3 4
样例输出
28
5
程序分析
友情提示

(1) 每个数字出现了偶数次会抵消。例如2 2 2当作一个2来处理,3 3相当于没有数字。这个在题目中好象没有说。
(2) 一定要注意题目的第一句话,即“给定一些不同的一位数字”,所以(1)的说明是多余的,那么每组测试数据的长度最长为10
(3)神坑神坑神坑:给出的样例输入,N个数字的最后并没有空格;隐藏的测试样本中,N个数字之后有空格。
在这里插入图片描述

strip ()去掉字符串两边的空格
lstrip()去掉左边的空格
rstrip()去掉右边的空格
当参数为空时,默认删除空白符(包括’\n’, ‘\r’, ‘\t’, ’ ')
for i in range(T):
    N = int(input())
    # 额外加入-1,使得下标从1开始
    numList = [-1] + list(map(int, input().rstrip().split(' ')))    # 去掉每一行数字后面的空格
    # numList = [-1] + list(map(int, input().split(' ')))
    # 使用这个获取N个数字 ValueError: invalid literal for int() with base 10:
    # 即要转换成int型的文本不符合10进制类型,就是因为有空格的存在
    numList.sort()
    absMin()
解题思路1
  1. 首先读入数码,然后排序
  2. 分类讨论
  •  当只有两个数码的时候是特殊情况,直接输出大的减去小的
  •   如果有奇数个数码,那么组成了[n/2]和[n/2]+1位数,使得[n/2]+1位数尽可能的小,[n/2]位数尽可能大,如果有零,则要安排在[n/2]+1位数的次高位上,比如0,1,2,3,5,7,9就要被组合成1023和975这种情况。所以,具体的方法就是,将最小的非0数字作为x的最高位,然后依次从左往右取k位加入(n-1)/2,从右往左取(n-1)/2位作为y,x-y的绝对值即为答案 (贪心思想:大数尽可能小,小数尽可能大)
  •  如果是偶数个数码,那么枚举最高位(一定是排序后相邻的两个),然后使得大数尽可能小,小数尽可能大。比如:0,1,2,4,6,7就要枚举1,2;2,4;4,6;6,7是最高位的情况依次计算求出最小差值。枚举非零数字a[i]作为x的最高位,a[i+1]作为y的最高位,从右往左取(n-2)/2位加入x,从左往右取(n-2)/2位加入y,不断地迭代更新答案。 (贪心思想:大数尽可能小,小数尽可能大)
代码
class absMin:
    def __init__(self):
        if N == 2:
            print(abs(numList[1] - numList[2]))
        elif N % 2 == 1:
            print(self.oddNumber())
        else:
            print(self.evenNumber())

    def oddNumber(self):
        a, b = 0, 0
        if numList[1] == 0:  # 不能用0做最高位
            numList[1], numList[2] = numList[2], 0
        # N为奇数时,下标为[1:N],(N+1)/2是中位数
        for i in range(1, (N + 1) // 2 + 1):    # 选取非0最小数做最高位,从左往右取(n-1)/2位数
            a = 10 * a + numList[i]
        for ii in range(N, (N + 1) // 2, -1):   # 选取最大数做最高位,从右往左取(n-1)/2位数
            b = 10 * b + numList[ii]
        return abs(a - b)

    def evenNumber(self):
        a, b, minABS = 0, 0, 1000000000
        start = 1
        if numList[1] == 0:  # 不能用0做首位
            start = 2
        for i in range(start, N):
            a, b = numList[i], numList[i + 1]
            lb, ub = 1, N
            flag = [0] * (N + 1)
            flag[i], flag[i + 1] = 1, 1  # 标记已用
            for times in range(1, (N - 2) // 2 + 1):
                while flag[lb]:
                    lb = lb + 1
                while flag[ub]:
                    ub = ub - 1
                a = a * 10 + numList[ub]
                b = b * 10 + numList[lb]
                flag[lb], flag[ub] = 1, 1
            minABS = min(minABS, abs(a - b))
        return minABS


T = int(input())
for i in range(T):
    N = int(input())
    # 额外加入-1,使得下标从1开始
    numList = [-1] + list(map(int, input().rstrip().split(' ')))    # 去掉每一行数字后面的空格
    # numList = [-1] + list(map(int, input().split(' ')))
    # 使用这个获取N个数字 ValueError: invalid literal for int() with base 10:
    # 即要转换成int型的文本不符合10进制类型,就是因为有空格的存在
    numList.sort()
    absMin()

  1. https://blog.csdn.net/qq_31640513/article/details/60335931 ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

还能坚持

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

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

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

打赏作者

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

抵扣说明:

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

余额充值