面试街三胞胎挑战赛

时间:2012-12-18 07:54:08

标签: algorithm

有一个整数数组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个测试用例通过。 请帮忙解决这个问题。

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件物品。由于物品已经排序,因此也会订购三个选定的物品
  • IIRC有(n!)/((n-3)!* 3!)方式来挑选这三个项目; n:=唯一项目数

答案 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'可能的三元组:

  • 4 4
  • 5 10
  • 6 20
  • 7 35
  • 8 56
  • 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 
                */
            }
        }
    }
}

结果=散列中的三元组数;

我没有尝试,但我认为它应该有用。