我一直在努力应对这一挑战:Count Triplets,经过大量的努力,我的算法并未在每个测试用例中都可以解决。
由于在讨论中,我看到了一个代码并试图找出该代码的真正功能,所以我仍然无法理解该代码是如何工作的。
解决方案:
from collections import defaultdict
arr = [1,3,9,9,27,81]
r = 3
v2 = defaultdict(int)
v3 = defaultdict(int)
count = 0
for k in arr:
count += v3[k]
v3[k*r] += v2[k]
v2[k*r] += 1
print(count)
上面的代码完美地适用于每个测试用例。我已经测试了k
,v2
,v3
的值,以了解但仍然不了解代码如何在计数三胞胎时如此平稳。我也梦in以求的解决方案。我想知道人们如何聪明地制定出这种解决方案。不过,如果能得到适当的解释,我将感到高兴。谢谢
k,v2,v3的输出
from collections import defaultdict
arr = [1,3,9,9,27,81]
r = 3
v2 = defaultdict(int)
v3 = defaultdict(int)
count = 0
for k in arr:
count += v3[k]
v3[k*r] += v2[k]
v2[k*r] += 1
print(k, count, v2, v3)
输出
1 0 defaultdict(<class 'int'>, {1: 0, 3: 1}) defaultdict(<class 'int'>, {1: 0, 3: 0})
3 0 defaultdict(<class 'int'>, {1: 0, 3: 1, 9: 1}) defaultdict(<class 'int'>, {1: 0, 3: 0, 9: 1})
9 1 defaultdict(<class 'int'>, {27: 1, 1: 0, 3: 1, 9: 1}) defaultdict(<class 'int'>, {27: 1, 1: 0, 3: 0, 9: 1})
9 2 defaultdict(<class 'int'>, {27: 2, 1: 0, 3: 1, 9: 1}) defaultdict(<class 'int'>, {27: 2, 1: 0, 3: 0, 9: 1})
27 4 defaultdict(<class 'int'>, {27: 2, 1: 0, 3: 1, 81: 1, 9: 1}) defaultdict(<class 'int'>, {27: 2, 1: 0, 3: 0, 81: 2, 9: 1})
81 6 defaultdict(<class 'int'>, {1: 0, 3: 1, 243: 1, 81: 1, 9: 1, 27: 2}) defaultdict(<class 'int'>, {1: 0, 3: 0, 243: 1, 81: 2, 9: 1,
27: 2})
答案 0 :(得分:1)
因此,代码在遍历数组时正在跟踪潜在的对和三元组。
For each value in the array:
// Increment count by the number of triplets that end with k
count += v3[k]
// Increment the number of potential triplets that will end with k*r
v3[k*r] += v2[k]
// Increment the number of potential pairs that end with k*r
v2[k*r] += 1
任何给定k的三元组数是到目前为止我们遇到的任何给定k / r的对数。 请注意,在整个循环中,v3 [k]和v2 [k]通常会为零,直到它们达到上一次迭代的预测k * r值为止。
答案 1 :(得分:1)
该函数有两个参数,即:
因此,输入内容可能类似于
arr: [1, 2, 2, 4]
r: 2
目标是返回形成几何级数的三元组的数量。
要解决此问题,有多种方法。例如,根据SagunB
从comment from RobertsN
- 可以在O(n)->单次通过数据中完成
- 不需要除法,只需要乘以R即可
- 必须使用map(C ++)或dict(Java,Python)->可以是无序映射(节省O(logN))
- 在读取值时尝试思考->以后该值会成为三元组的一部分吗?
- 无需考虑(R == 1)作为极端情况
from collections import Counter
# Complete the countTriplets function below.
def countTriplets(arr, r):
r2 = Counter()
r3 = Counter()
count = 0
for v in arr:
if v in r3:
count += r3[v]
if v in r2:
r3[v*r] += r2[v]
r2[v*r] += 1
return count
或者就像你说的
from collections import defaultdict
# Complete the countTriplets function below.
def countTriplets(arr, r):
v2 = defaultdict(int)
v3 = defaultdict(int)
count = 0
for k in arr:
count += v3[k]
v3[k*r] += v2[k]
v2[k*r] += 1
return count
两个案例都将通过HackerRank中的所有13个测试案例
RobertsN的评论在很大程度上解释了您的代码(与您的代码非常相似)。尽管如此,为了更好地了解代码的工作原理,只需打印v2和v3的计数即可。
假设您将输入
4 2
1 2 2 4
预期输出是
2
此外,我们知道definition的v2和v3都将看起来像
defaultdict(<class 'int'>, {})
留下了for循环需要理解。可能引起混淆的是运算符+ =,但这是already addressed by me in another answer。
因此,现在要了解其余内容,我们可以将循环更改为
for k in arr:
print(f"Looping...")
print(f"k: {k}")
print(f"v3_before_count: {v3}")
count += v3[k]
print(f"count: {count}")
print(f"k*r: {k*r}")
print(f"v3_before: {v3}")
v3[k*r] += v2[k]
print(f"v3[k*r]: {v3[k*r]}")
print(f"v2[k]: {v2[k]}")
print(f"v3_after: {v3}")
print(f"v2_before: {v2}")
v2[k*r] += 1
print(f"v2_after: {v2}")
print(f"v2[k*r]: {v2[k*r]}")
将允许您查看
Looping...
k: 1
v3_before_count: defaultdict(<class 'int'>, {})
count: 0
k*r: 2
v3_before: defaultdict(<class 'int'>, {1: 0})
v2_before_v3: defaultdict(<class 'int'>, {1: 0})
v3[k*r]: 0
v2[k]: 0
v3_after: defaultdict(<class 'int'>, {1: 0, 2: 0})
v2_before: defaultdict(<class 'int'>, {1: 0})
v2_after: defaultdict(<class 'int'>, {1: 0, 2: 1})
v2[k*r]: 1
Looping...
k: 2
v3_before_count: defaultdict(<class 'int'>, {1: 0, 2: 0})
count: 0
k*r: 4
v3_before: defaultdict(<class 'int'>, {1: 0, 2: 0})
v2_before_v3: defaultdict(<class 'int'>, {1: 0, 2: 0})
v3[k*r]: 1
v2[k]: 1
v3_after: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 1})
v2_before: defaultdict(<class 'int'>, {1: 0, 2: 1})
v2_after: defaultdict(<class 'int'>, {1: 0, 2: 1, 4: 1})
v2[k*r]: 1
Looping...
k: 2
v3_before_count: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 1})
count: 0
k*r: 4
v3_before: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 1})
v2_before_v3: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 1})
v3[k*r]: 2
v2[k]: 1
v3_after: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 2})
v2_before: defaultdict(<class 'int'>, {1: 0, 2: 1, 4: 1})
v2_after: defaultdict(<class 'int'>, {1: 0, 2: 1, 4: 2})
v2[k*r]: 2
Looping...
k: 4
v3_before_count: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 2})
count: 2
k*r: 8
v3_before: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 2})
v2_before_v3: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 2})
v3[k*r]: 2
v2[k]: 2
v3_after: defaultdict(<class 'int'>, {1: 0, 2: 0, 4: 2, 8: 2})
v2_before: defaultdict(<class 'int'>, {1: 0, 2: 1, 4: 2})
v2_after: defaultdict(<class 'int'>, {1: 0, 2: 1, 4: 2, 8: 1})
v2[k*r]: 1
并提取所需的疾病。从中我们可以观察到什么?
此过程很可能会引发问题,回答这些问题会使您更加了解它。
答案 2 :(得分:1)
我一直试图理解它,最后,这个 C# 代码应该很清楚
static long countTriplets(List<long> arr, long r)
{
//number of times we encounter key*r
var doubles = new Dictionary<long, long>();
//number of times we encounter a triplet
var triplets = new Dictionary<long, long>();
long count = 0;
foreach (var key in arr)
{
long keyXr = key * r;
if (triplets.ContainsKey(key))
count += triplets[key];
if (doubles.ContainsKey(key))
{
if (triplets.ContainsKey(keyXr))
triplets[keyXr] += doubles[key];
else
triplets.Add(keyXr, doubles[key]);
}
if (doubles.ContainsKey(keyXr))
doubles[keyXr]++;
else
doubles.Add(keyXr, 1);
}
return count;
}
答案 3 :(得分:0)
from collections import defaultdict
arr = [1,3,9,9,27,81]
r = 3
v2 = defaultdict(int) #if miss get 0
v3 = defaultdict(int) #if miss get 0
count = 0`enter code here`
for k in arr:
#updating the count, starts propagating with delay=2 elements
count += v3[k]
# number of triplets with last component ending
# on index i of k in array
v3[k*r] += v2[k]
# number of pairs with last component ending
# on index i of k in array
v2[k*r] += 1
print(count)
最好通过示例来理解 - 假设我们有数组 11111, 我们在 i=3 上,所以 111>1<1.
v2 当前计数为 111, 11>1< 有两对以 >1< 结尾,通常 n-1 表示 length(array)=n。
现在在 v3 我们从 v2 递归构造计数,如下所示:对于用 v2 创建和计数的每一对,我们分配最后一个组件有 n 个这样的选项 对于#pairs = n。
所以对于 i=3:
11.1 (v2=1) //this pair remains by sum
+
.111 (v2=2) //these are new
1.11 (v2=2)
希望这会有所帮助!