[英]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.