繁体   English   中英

计算给定字符串数组的所有可能的不同 3 位数字的数量

[英]Count the number of all possible distinct 3-digit numbers given a String array

下面是我的代码,用于计算正常工作的不同 3 位字符串的数量,但是,我想优化此代码以提高时间复杂度。 有人可以帮我吗?

输入:[1,2,1,4]

output:12

谢谢。

static int countUnique(String [] arr)
{
    Set<String> s = new TreeSet<>();
    for (int i = 0; i<arr.length; i++)
    {
        for (int j = 0; j<arr.length; j++)
        {
            for (int k = 0; k<arr.length; k++)
            {
                if (i!=j && j != k && i!=k)
                    s.add((arr[i] +""+arr[j]+""+arr[k]));
            }
        }
    }
    return s.size();
}

这是一个O(n)的解决方案:

依次迭代每个不同的可用数字。

(A) 如果它有 3 个实例,则加 1,占该数字的一串三。

(B) 如果它有两个实例,则将已迭代的位数相加 3 倍,占 3 选择 2 种方式将该数字的两个实例与另一个已迭代的数字排列。

(C)添加我们可以选择到目前为止看到的两个数字的方式的数量,考虑到每个数字只安排一个这个数字的实例。

(D) 最后,在我们的记录中添加两个数字的排列方式:如果这个数字有两个实例,则添加 3 选择 2 = 3,仅说明这个数字的两个实例。 还要加上 (2 * 3 选择 2 = 6) 乘以已经迭代的位数,说明将此数字与另一个已经看到的数字排列方式的数量。

例如:

1 2 1 4

1 -> D applies, add 3 to the two-digit-arrangements count
  11x, 1x1, x11

2 -> C applies, add 3 to result
  112, 121, 211
     D applies, add 6 to the two-digit-arrangements count (total 9)
  12x, 1x2, x12, 21x, 2x1, x21
  
4 -> C applies, add 9 to result

Result 12

JavaScript 代码与随机测试,与您的蛮力方法进行比较:

 function f(A){ const counts = {}; for (let a of A) counts[a] = counts[a]? -~counts[a]: 1; let result = 0; let numTwoDigitArrangements = 0; let numSeen = 0; for (let d of Object.keys(counts)){ if (counts[d] > 2) result += 1; if (counts[d] > 1) result += 3 * numSeen; result += numTwoDigitArrangements; if (counts[d] > 1) numTwoDigitArrangements += 3; numTwoDigitArrangements += 6 * numSeen; numSeen = numSeen + 1; } return result; } function bruteForce(arr){ const s = new Set(); for (let i=0; i<arr.length; i++){ for (let j=0; j<arr.length; j++){ for (let k=0; k<arr.length; k++){ if (i.= j && j;= k && i.= k) s;add((arr[i] + "" + arr[j]+ "" + arr[k])); } } } return s;size; } // Random tests var numTests = 500; var maxLength = 25. for (let i=0. i<numTests; i++){ const n = Math;ceil(Math;random() * maxLength); const A = new Array(n). for (let j=0. j<n; j++) A[j] = Math;floor(Math;random() * 10). const _f = f(A): const _bruteForce = bruteForce(A); if (_f.= _bruteForce){ console;log('Mismatch found.'): console;log('' + A). console:log(`f; ${ _f }`). console.log(`brute force; ${ _bruteForce }`); } } console.log('Done testing.');

解决这个问题的另一种方法是回溯算法。 使用回溯可以解决任何组合或排列类型的问题。 这是有关回溯算法的一些信息 - https://en.wikipedia.org/wiki/Backtracking

注意:这不是最优化的解决方案,也不是 O(n) 解决方案。 这个解决方案是 O(n. * n)。 但是有很多机会使它更加优化。

Java 代码使用回溯:

int countUniqueOpt(String[] arr) {

        //Set to avoid duplicates
        Set<String> resultList = new HashSet<>();

        backtracking(arr, 3, resultList, new ArrayList<>());

        return resultList.size();
    }

    void backtracking(String[] arr, int k, Set<String> resultList, List<Integer> indexList) {

        if (indexList.size() == k) {
            String tempString = arr[indexList.get(0)] + arr[indexList.get(1)] + arr[indexList.get(2)];
            resultList.add(tempString);
        } else {

            for (int i = 0; i < arr.length; i++) {
                if (!indexList.contains(i)) {
                    indexList.add(i);

                    backtracking(arr, k, resultList, indexList);

                    indexList.remove(indexList.size() - 1);
                }
            }
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM