我遇到了要解决的挑战:
在军队中,每个士兵都有一个指定的军衔。 X级士兵必须向X + 1级(任何)士兵报告。许多士兵可以向同一上级报告。
编写一个函数:
def solution(ranks): # write your code in Python 3.6 return len([i for i in ranks if i + 1 in ranks])
在给定由士兵等级组成的数组等级的情况下,返回可以向上级报告的士兵人数。示例:
给定等级= [3,4,3,0,2,2,2,3,0,0],您的函数应返回5,因为:
- 三名三级士兵(等级[0],等级[2],等级[6])可以向四级士兵(等级[1])报告。
- 两名2级士兵可以向任何3级士兵报告。
给定等级= [4,2,0],您的函数应返回0。
给定等级= [4,4,3,3,1,0],您的函数应返回3,因为:
- 0级士兵可以向1级士兵报告。
- 两名3级士兵可以向任何4级士兵报告。
为以下假设写出有效的算法:
- N是[2..100,000]范围内的整数;
- 数组等级的每个元素都是[0..1,000,000,000]范围内的整数。
我提出了解决方案来解决它:
large_random
large random test
✘ TIMEOUT ERROR
running time: 3.196 sec., time limit: 0.528 sec.
large_sorted
large sorted array
✘ TIMEOUT ERROR
running time: 3.712 sec., time limit: 0.464 sec.
large_distinct
large distinct array
✘ TIMEOUT ERROR
Killed. Hard limit reached: 6.000 sec.
one_or_two_giant_pyramids
concatenated one or two dense (almost each K counts to the result) subarrays
✘ TIMEOUT ERROR
running time: 4.216 sec., time limit: 0.736 sec.
random_max_values
maximum size array containing maximum values
✘ TIMEOUT ERROR
Killed. Hard limit reached: 7.000 sec.
two_values_repeated
maximum size array with only two distinct values
✘ TIMEOUT ERROR
Killed. Hard limit reached: 7.000 sec.
此算法的复杂度为O(N²)。 我想知道是否有一种方法可以减少它并做出更快的算法,因为我为此得到了TIMEOUT_ERROR。
{{1}}
答案 0 :(得分:3)
您可以通过计算最低级别(数字最高)的人数来找到不报告给其他人的士兵的数量,这可以在O(N)时间内完成;将其转换为要做的人数,在最坏的情况下将花费另一个O(N)时间(但可以在O(1)中完成)。
答案 1 :(得分:3)
首先将ranks
设置为集合要快得多:
import timeit
r = [4, 2, 1, 3, 3, 2, 3, 5, 4] * 100
def solution1(ranks):
return len([i for i in ranks if i+1 in ranks])
def solution2(ranks):
rank_set = set(ranks)
return len([i for i in ranks if i+1 in rank_set])
print(timeit.timeit(lambda: solution1(r), number=1000))
print(timeit.timeit(lambda: solution2(r), number=1000))
输出:
1.8472468510000002
0.13349082600000006
答案 2 :(得分:3)
另一种使用collections.Counter
的解决方案(但是@ user10987432解决方案更干净-没有任何外部模块):
def solution_2(ranks):
c = Counter(ranks)
return sum(c[k] if k+1 in c else 0 for k in c)
基准:
from timeit import timeit
from collections import Counter
lst = [3, 4, 3, 0, 2, 2, 3, 0, 0] * 100
def solution_1(ranks):
return len([i for i in ranks if i + 1 in ranks])
def solution_2(ranks):
c = Counter(ranks)
return sum(c[k] if k+1 in c else 0 for k in c)
def solution_3(ranks):
rank_set = set(ranks)
return len([i for i in ranks if i+1 in rank_set])
t1 = timeit(lambda: solution_1(lst), number=1000)
t2 = timeit(lambda: solution_2(lst), number=1000)
t3 = timeit(lambda: solution_3(lst), number=1000)
print(t1)
print(t2)
print(t3)
打印:
4.242018623999684
0.039016962999994576
0.05872536300012143
答案 3 :(得分:1)
根据我的评论,这是一个已实现的想法:
def solution(ranks):
ranks.sort(key=lambda x: -x)
is_group_ok = False
result = 0
for i in range(1, len(ranks)):
if ranks[i] + 1 == ranks[i - 1]:
result += 1
is_group_ok = True
elif ranks[i] == ranks[i - 1] and is_group_ok:
result += 1
else:
is_group_ok = False
return result
基于集合的解决方案将执行相同或更好的操作,但这是基于算法的解决方案(与使用set
相对),这可能是可取的,也可能不是优选的。无论如何都要包括在内