有一个整数数组d,它不包含两个以上相同值的元素。存在多少个不同的上升三元组(d [i]< d [j]< d [k],i< j< k)?
输入格式:
第一行包含一个整数N,表示数组中的元素数。接下来是一行包含N个整数,由单个空格分隔,没有前导/尾随空格
输出格式:
一个整数,表示数组中存在的不同上升三元组的数量
约束:
N <= 10 ^ 5 数组中的每个值最多出现两次 数组中的每个值都是32位正整数
示例输入:
6 1 1 2 2 3 4
示例输出:
4
解释
不同的三胞胎是
(1,2,3)
(1,2,4)
(1,3,4)
(2,3,4)
另一个测试案例:
输入:
10 1 1 5 4 3 6 6 5 9 10
输出:
28
我尝试用DP解决。但在15个测试案例中,只有7个测试用例通过。 请帮忙解决这个问题。
答案 0 :(得分:8)
您应该注意,您只需要知道比特定元素更小/更大的元素数量,以了解它作为中间点的三元组数量。使用它你可以很容易地计算三元组的数量,唯一剩下的问题是摆脱重复,但鉴于你被限制在同一元素的最多2个,这是微不足道的。
我使用二进制索引树http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees解决了问题。
我也做了一个小小的写作,http://www.kesannmcclean.com/?p=223。
答案 1 :(得分:1)
对于我想出的暂定算法,它应该是:
(K-1)!^2
其中K是唯一元素的数量。
修改强>
经过更多思考:
SUM[i=1,K-2] SUM[j=i+1,K-1] SUM[m=j+1,K] 1
=> SUM[i=1,K-2] (SUM[j=i+1,K-1] (K-j))
答案 2 :(得分:1)
答案 3 :(得分:1)
package com.jai;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
public class Triplets {
int[] lSmaller, rLarger, treeArray, dscArray, lFlags, rFlags;
int size, count = 0;
Triplets(int aSize, int[] inputArray) {
size = aSize;
lSmaller = new int[size];
rLarger = new int[size];
dscArray = new int[size];
int[] tmpArray = Arrays.copyOf(inputArray, inputArray.length);
Arrays.sort(tmpArray);
HashMap<Integer, Integer> tmpMap = new HashMap<Integer, Integer>(size);
for (int i = 0; i < size; i++) {
if (!tmpMap.containsKey(tmpArray[i])) {
count++;
tmpMap.put(tmpArray[i], count);
}
}
count++;
treeArray = new int[count];
lFlags = new int[count];
rFlags = new int[count];
for (int i = 0; i < size; i++) {
dscArray[i] = tmpMap.get(inputArray[i]);
}
}
void update(int idx) {
while (idx < count) {
treeArray[idx]++;
idx += (idx & -idx);
}
}
int read(int index) {
int sum = 0;
while (index > 0) {
sum += treeArray[index];
index -= (index & -index);
}
return sum;
}
void countLeftSmaller() {
Arrays.fill(treeArray, 0);
Arrays.fill(lSmaller, 0);
Arrays.fill(lFlags, 0);
for (int i = 0; i < size; i++) {
int val = dscArray[i];
lSmaller[i] = read(val - 1);
if (lFlags[val] == 0) {
update(val);
lFlags[val] = i + 1;
} else {
lSmaller[i] -= lSmaller[lFlags[val] - 1];
}
}
}
void countRightLarger() {
Arrays.fill(treeArray, 0);
Arrays.fill(rLarger, 0);
Arrays.fill(rFlags, 0);
for (int i = size - 1; i >= 0; i--) {
int val = dscArray[i];
rLarger[i] = read(count - 1) - read(val);
if (rFlags[val] == 0) {
update(val);
rFlags[val] = i + 1;
}
}
}
long countTriplets() {
long sum = 0;
for (int i = 0; i < size; i++) {
sum += lSmaller[i] * rLarger[i];
}
return sum;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] a = new int[N];
String[] strs = br.readLine().split(" ");
for (int i = 0; i < N; i++)
a[i] = Integer.parseInt(strs[i]);
Triplets sol = new Triplets(N, a);
sol.countLeftSmaller();
sol.countRightLarger();
System.out.println(sol.countTriplets());
}
}
答案 4 :(得分:0)
@hadron:确切地说,我无法理解为什么它应该 28 而不是 35 一组7个不同的数字*
[由于问题是关于提升三胞胎,重复的数字可以被丢弃]。
顺便说一下,这是一个非常糟糕的Java解决方案(N ^ 3):
我还打印出了可能的三胞胎:
我也在思考一些函数,它决定了输入'N'可能的三元组:
9 84
package org.HackerRank.AlgoChallenges;
import java.util.Iterator; import java.util.Scanner; import java.util.TreeSet;
public class Triplets {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int result = 0;
int n = scanner.nextInt();
Object[] array = new Object[n];
TreeSet<Integer> treeSet = new TreeSet<Integer>();
/*
* for (int i = 0; i < n; i++) { array[i] = scanner.nextInt(); }
*/
while (n>0) {
treeSet.add(scanner.nextInt());
n--;
}
scanner.close();
Iterator<Integer> iterator = treeSet.iterator();
int i =0;
while (iterator.hasNext()) {
//System.out.println("TreeSet["+i+"] : "+iterator.next());
array[i] = iterator.next();
//System.out.println("Array["+i+"] : "+array[i]);
i++;
}
for (int j = 0; j < (array.length-2); j++) {
for (int j2 = (j+1); j2 < array.length-1; j2++) {
for (int k = (j2+1); k < array.length; k++) {
if(array[j]!=null && array[j2]!=null && array[k]!=null){
System.out.println("{ "+array[j]+", "+array[j2]+", "+array[k]+" }");
result++;
}
}
}
}
System.out.println(result);
}
答案 5 :(得分:0)
python中的一个解决方案:
from itertools import combinations as comb
def triplet(lis):
done = dict()
result = set()
for ind, num in enumerate(lis):
if num not in done:
index = ind+1
for elm in comb(lis[index:], 2):
s,t = elm[0], elm[1]
if (num < s < t):
done.setdefault(num, None)
fin = (num,s,t)
if fin not in result:
result.add(fin)
return len(result)
test = int(raw_input())
lis = [int(_) for _ in raw_input().split()]
print triplet(lis)
答案 6 :(得分:-1)
你关心复杂性吗?
输入数组是否已排序?
如果你不介意复杂性,你可以用N ^ 3的复杂性来解决它。
复杂度为N ^ 3的解决方案: 如果没有排序,则对数组进行排序。 在另一个内部使用3 for循环,并为每个数字抛出数组3次。 使用哈希映射来计算所有三元组。关键是它自己的三倍,值将是出现次数。
它应该是这样的:
for (i1=0; i1<N; i1++) {
for (i2=i1; i2<N; i2++) {
for (i3=i2; i3<N; i3++) {
if (N[i1] < N[i2] < N[i3]) {
/* if the triple exists in the hash then
add 1 to its value
else
put new triple to the hash with
value 1
*/
}
}
}
}
结果=散列中的三元组数;
我没有尝试,但我认为它应该有用。