题目描述
给定一些不同的一位数字,你可以从这些数字中选择若干个,并将它们按一定顺序排列,组成一个整数,把剩下的数字按一定顺序排列,组成另一个整数。组成的整数不能以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
- 首先读入数码,然后排序
- 分类讨论
- 当只有两个数码的时候是特殊情况,直接输出大的减去小的
- 如果有奇数个数码,那么组成了[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()
https://blog.csdn.net/qq_31640513/article/details/60335931 ↩︎