我正在编码网站上处理一个问题并且在解决它时遇到了一些问题。问题是:
打印1到N - 数字计数[ZOHO]
传递正整数N作为输入。如果我们打印所有的 数字从1到N连续,程序必须找到数字 字符(数字)C打印并打印计数C作为输出。
输入格式:第一行包含N。
输出格式:第一行包含C。
边界条件:1< = N< = 9999999
示例输入/输出1:输入:2
输出:2
说明:我们打印12,因此总字符数是 2。
示例输入/输出2:输入:15
输出:21
说明:我们打印123456789101112131415,因此总数 人物是21。
我解决了问题,但我的代码没有通过所有测试用例(它们被隐藏)。这是我的代码:
n = int(input())
assert 1<=n<=9999999
a = [str(i) for i in range(1,n+1)]
b = ''.join(a)
print(len(b))
这是解决问题的正确方法,还是有其他方法可以解决这个问题?
答案 0 :(得分:2)
由于这是一个 Math 问题,我最好使用更多数学方法,因为它会使用更少的内存并且效率会更高。
这是我的方法。
计算数字的长度。
- 如果
length = 1
,则保证您拥有9x1
个字符。- 如果
length = 2
,则保证您拥有9x1 + 90x2
个字符。- 如果
length = 3
,则保证您拥有9x1 + 90x2 + 900x3
个字符,等等......我希望你能在这里看到循环。
- 醇>
对于其余部分,请举例
1234
,1234 - 1000 = 234
数字 length =数字的长度。不,错误:234 +1 = 235个数字 length =数字的长度!
在代码中制定它。
n = input()
length = len(n)
x,s = 9,0
for i in range(1,length):
s=s+x*i
x = x*10 # 9-> 90-> 900->
print(s+(int(n)-10**(length-1)+1)*length) # 234 + 1
# 1234 - 10^3
# = 234 +1
# = 235 * 4(length) = ...
>>> 1234
3829
>>>> 15
21
我也import time
看到了效率。对于n=9999999
,您的代码大约需要 3.26秒,而此代码需要 160-200 usec 。
答案 1 :(得分:1)
这里的版本使用与Miraj50的答案基本相同的算法,除了它不需要循环来计算数字长度比当前输入数字少的数字。我在这个OEIS条目的帮助下开发了我的公式:A033713&#34;数字1到999..9(n位)&#34;中的零数。
我将添加一个稍微修改过的Miraj50代码版本,以及Blender评论中给出的暴力版本,以表明它们都给出了相同的结果。
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
guard let applicationBundleId = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String else {
return true
}
// Save your source application
sourceApplicationBundleId = applicationBundleId
return true
}
var sourceApplicationBundleId: String?
// Attempt to open application from which your app was opened
func openApplication() {
guard let applicationBundleId = sourceApplicationBundleId, let url = url(for: applicationBundleId) else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
func url(for bundleId: String) -> URL? {
guard let scheme = knownUrlSchemes[bundleId] else {
return nil
}
return URL(string: scheme)!
}
// A list of known url schemes
var knownUrlSchemes: Dictionary<String, String> = {
return ["com.google.Maps": "comgooglemaps://",
"com.facebook.Facebook": "fb://"]
}()
<强>输出强>
def nlen_blender(n):
return sum(len(str(i)) for i in range(1,n+1))
def nlen_miraj(n):
length = len(str(n))
x, s = 9, 0
for i in range(1,length):
s = s + x*i
x = x*10
return s + (n - 10**(length-1) + 1) * length
def nlen_pm2r(n):
digits = len(str(n))
a = 10 ** (digits - 1)
return (n + 1) * digits - a - (a - 1) // 9
# test
funcs = (nlen_blender, nlen_miraj, nlen_pm2r)
data = (0, 1, 37, 563, 4285, 12900, 375462)
for n in data:
print(n)
for f in funcs:
print('{:13}: {}'.format(f.__name__, f(n)))
print()
n = 12398765434324
print(n)
for f in (nlen_miraj, nlen_pm2r):
print(f(n))
这是一个进行0
nlen_blender : 0
nlen_miraj : 0
nlen_pm2r : 0
1
nlen_blender : 1
nlen_miraj : 1
nlen_pm2r : 1
37
nlen_blender : 65
nlen_miraj : 65
nlen_pm2r : 65
563
nlen_blender : 1581
nlen_miraj : 1581
nlen_pm2r : 1581
4285
nlen_blender : 16033
nlen_miraj : 16033
nlen_pm2r : 16033
12900
nlen_blender : 53394
nlen_miraj : 53394
nlen_pm2r : 53394
375462
nlen_blender : 2141667
nlen_miraj : 2141667
nlen_pm2r : 2141667
12398765434324
162471604969439
162471604969439
测试的版本。正如您所看到的,消除timeit
循环会加快速度,尤其是当for
很大时。
n
<强>输出强>
from timeit import Timer
def nlen_miraj(n):
length = len(str(n))
x, s = 9, 0
for i in range(1,length):
s = s + x*i
x = x*10
return s + (n - 10**(length-1) + 1) * length
def nlen_pm2r(n):
digits = len(str(n))
a = 10 ** (digits - 1)
return (n + 1) * digits - a - (a - 1) // 9
def time_test(num, loops):
timings = []
for func in funcs:
t = Timer(lambda: func(num))
result = sorted(t.repeat(3, loops))
timings.append((result, func.__name__))
timings.sort()
for result, name in timings:
print('{:13} : {}'.format(name, result))
print()
funcs = (nlen_miraj, nlen_pm2r)
data = (0, 1, 37, 563, 4285, 12900, 375462, 12398765434324)
loops = 10000
for n in data:
print(n)
time_test(n, loops)
这些时间是在我在Debian衍生Linux上运行Python 3.6.0的旧2GHz 32位机器上获得的。
答案 2 :(得分:0)
我发现了两种新的方法,第一种方法使用类似于Miraj50的方法(我在发布它的时候,因为为了完整性而将它保留在这里),以for
循环的方式而第二个使用向量代数来计算它,它也可以在numpy中实现,这可以改善其对大数字的性能。您可以在以下部分中将它们视为方法a
和b
。
我用以下脚本做了一些时间安排。随意修改INPUTS
和REPETITIONS
。它需要一段时间,因为它正在执行REPETITIONS * len(INPUTS)
次每个方法,len(INPUTS)
倍OP的方法来验证结果。它计算样本的均值,中位数和标准差,并以漂亮的表格格式打印出来。如果要添加新方法,只需定义函数并将其包含在methods
字典中。
# Values to test
INPUTS = [7, 9, 53, 99, 999, 9999, 99999, 999999, 9999999]
# Number of repetitions
REPETITIONS = 30000
from timeit import default_timer as timer
def a(n): # Iterative method
#n = input("Insert a number: ")
start = timer()
l = len(n)
if l == 1: # Special case as int("9"*0) raises ValueError
c = int(n)
else:
n, c = int(n), 9
for i in range(2, n+1):
if l == i:
c += (n - int("9"*(i-1))) * i
break
c += int("9"+ "0"*(i-1)) * i
print(c)
end = timer()
return c, end - start
def b(n): # No-loop method
#n = input("Insert a number: ")
start = timer()
l = len(n)
n = int(n)
aux = [9*10**i for i in range(l-1)]
aux.append(n - sum(aux))
c = sum((v*(i+1) for i, v in enumerate(aux)))
print(c)
end = timer()
return c, end - start
def c(n): # Miraj50's method
#n = input("Insert a number: ")
start = timer()
l = len(n)
x, c = 9, 0
for i in range(1, l):
c = c + x*i
x = x * 10
c = c + (int(n) - 10**(l-1) + 1) * l
print(c)
end = timer()
return c, end - start
def d(n): # Pm2 Ring's method
#n = input("Insert a number: ")
start = timer()
l = len(n)
a = 10 ** (l - 1)
c = (int(n) + 1) * l - a - (a - 1) // 9
print(c)
end = timer()
return c, end - start
# Method mapper
methods = {
'Adirio 1': a,
'Adirio 2': b,
'Miraj50' : c,
'PM2 Ring': d,
}
methods_list = sorted(methods.keys())
# Calculate the results that are valid
results = []
for n in INPUTS:
results.append(len(''.join(str(i) for i in range(1, n+1))))
# Calculate the results by the different methods
times = {}
for n, result in zip(INPUTS, results):
t = {} # Store times
for key in methods:
aux1 = []
for i in range(REPETITIONS):
c, aux2 = methods[key](str(n))
if c != result:
raise ValueError("Method {} for n = {} yielded {} and {} was expected".format(key.upper(), n, c, result))
aux1.append(aux2)
aux1.sort()
mean = sum(aux1) / REPETITIONS
if REPETITIONS % 2 == 0:
median = (aux1[REPETITIONS//2 - 1] + aux1[REPETITIONS//2]) / 2
else:
median = aux1[(REPETITIONS-1)//2]
std_dev = (sum((x-mean)**2 for x in aux1)/(REPETITIONS-1))**.5
t[key] = {
'mean': mean,
'median': median,
'std_dev': std_dev,
'min': aux1[0],
'max': aux1[-1],
}
times[n] = t
# Print the results
for n, c in zip(INPUTS, results):
print()
print("N = {:<15}".format(n), end='')
for method in methods_list:
print("|{:^19}".format("Method {}".format(method)), end='')
print()
print("+".join(["-"*19]*(len(methods_list)+1)))
for metric in times[INPUTS[0]][methods_list[0]]:
print(" {:<12} [us] ".format(metric), end='')
for method in methods_list:
print("| {:>17.2f} ".format(times[n][method][metric] *10**6), end='')
print()
N = 7 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 12.76 | 14.95 | 13.49 | 13.13
min [us] | 10.21 | 12.03 | 10.94 | 10.57
mean [us] | 85.15 | 87.11 | 83.93 | 85.68
max [us] | 35319.77 | 37254.20 | 35428.07 | 35010.91
std_dev [us] | 1486.21 | 1480.59 | 1465.55 | 1483.09
N = 9 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 12.76 | 14.95 | 13.49 | 13.13
min [us] | 10.21 | 12.03 | 10.57 | 10.21
mean [us] | 84.94 | 87.42 | 86.09 | 85.72
max [us] | 34595.95 | 35712.49 | 36281.33 | 36368.85
std_dev [us] | 1485.61 | 1486.80 | 1489.28 | 1482.85
N = 53 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 13.86 | 15.32 | 13.86 | 13.49
min [us] | 10.94 | 12.03 | 10.94 | 10.94
mean [us] | 85.93 | 88.38 | 85.41 | 85.91
max [us] | 34776.45 | 38539.21 | 36581.07 | 36074.94
std_dev [us] | 1477.20 | 1489.63 | 1477.41 | 1485.53
N = 99 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 14.22 | 15.32 | 13.86 | 13.49
min [us] | 10.94 | 12.76 | 10.94 | 10.94
mean [us] | 88.21 | 88.46 | 86.46 | 87.04
max [us] | 40802.19 | 35949.14 | 36355.72 | 39536.51
std_dev [us] | 1518.92 | 1489.06 | 1488.02 | 1525.52
N = 999 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 14.59 | 16.04 | 14.22 | 13.49
min [us] | 12.03 | 13.13 | 11.30 | 10.57
mean [us] | 87.68 | 88.48 | 86.96 | 85.81
max [us] | 35570.64 | 36136.57 | 42908.73 | 36164.28
std_dev [us] | 1488.79 | 1482.06 | 1489.39 | 1481.22
N = 9999 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 15.32 | 16.41 | 14.22 | 13.49
min [us] | 12.40 | 13.49 | 11.67 | 10.57
mean [us] | 88.06 | 88.91 | 86.78 | 85.58
max [us] | 34688.20 | 34618.92 | 35010.55 | 40569.91
std_dev [us] | 1478.79 | 1473.64 | 1495.85 | 1480.70
N = 99999 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 16.04 | 17.14 | 14.59 | 13.49
min [us] | 13.13 | 14.22 | 11.67 | 10.94
mean [us] | 89.44 | 89.79 | 88.20 | 86.94
max [us] | 44273.23 | 42208.25 | 40763.54 | 37936.45
std_dev [us] | 1497.36 | 1482.44 | 1512.71 | 1495.37
N = 999999 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 16.41 | 17.50 | 14.59 | 13.49
min [us] | 13.86 | 14.59 | 12.03 | 10.94
mean [us] | 88.60 | 90.63 | 87.18 | 85.68
max [us] | 35199.80 | 36482.62 | 48330.99 | 51652.53
std_dev [us] | 1475.87 | 1485.87 | 1483.34 | 1491.72
N = 9999999 | Method Adirio 1 | Method Adirio 2 | Method Miraj50 | Method PM2 Ring
-------------------+-------------------+-------------------+-------------------+-------------------
median [us] | 17.14 | 17.87 | 14.95 | 13.86
min [us] | 14.22 | 15.32 | 12.40 | 11.30
mean [us] | 89.97 | 89.86 | 87.74 | 85.51
max [us] | 35618.05 | 35605.65 | 36453.44 | 34081.07
std_dev [us] | 1480.06 | 1467.89 | 1488.62 | 1475.57
在制表的5项措施中,您需要了解一些影响。由于OS的调度程序可能在算法中间执行不同的进程,因此某些时序具有相当大的错误,它们占用了他们真正需要的太多时间。这意味着max,或者考虑样本中所有值的均值和标准差给出的上限给出了不值得信赖的结果。最小值和中值都以不同的方式消除了这个真正长期的情况。基于中值和最小值的算法比较非常相似:所有算法都有类似的执行时间,@ PM2Ring版本稍快一些。