我解决了以下提供的Codilty问题。
一个整数M和一个由N个非负数组成的非空数组A 给出整数。数组A中的所有整数均小于或等于 M。
将0≤P≤Q
例如,考虑整数M = 6和数组A,这样:
A[0] = 3 A[1] = 4 A[2] = 5 A[3] = 5 A[4] = 2 There are exactly nine distinct slices: (0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2), (3, 3), (3, 4) and (4, 4).
目标是计算不同切片的数量。
编写函数:
class Solution {public int solution(int M,int [] A); }
,给定一个整数M和一个由N组成的非空数组A 整数,返回不同切片的数量。
如果不同切片的数量大于1,000,000,000,则 函数应返回1,000,000,000。
例如,给定整数M = 6和数组A使得:
A[0] = 3 A[1] = 4 A[2] = 5 A[3] = 5 A[4] = 2 the function should return 9, as explained above.
为以下假设写出有效的算法:
N是[1..100,000]范围内的整数; M是一个整数 范围[0..100,000];数组A的每个元素都是 范围[0..M]。
我的解决方案在这里
public static int solution(int M, int[] A) {
boolean[] visited = new boolean[M + 1];
int N = A.length;
int result = 0;
for (int i = 0; i < N; i++) {
int k = i;
int count = 0;
while (i < N && !visited[A[i]]) {
count++;
visited[A[i]] = true;
i++;
}
i -=1;
// 3, 4, 5, 5, 2, 5, 4
int j = i;
while (j >= k && visited[A[j]]) {
visited[A[j]] = false;
j--;
}
result += count * (count + 1) / 2;
}
return result;
}
但是,在线法官估计正确性和性能较低。我该如何改善?
答案 0 :(得分:2)
似乎您选择了正确的方法,但是在实现细节上却犯了错误-坏主意会降低索引。
制作两个索引-左和右。
a)向右移动,直到遇到重复的元素(“塞子”)-本质上,您在第一个while循环中执行此步骤。如果您在停止之前进行了n步操作-则有n *(n-1)/ 2个切片。
b)现在向左移动索引,直到找到与“ stopper”相同的元素,然后在其后停止。当前切片又好了
重复a)和b)直到结束。请注意,两个索引仅向前移动,并且复杂度是线性的
答案 1 :(得分:1)
我喜欢两个指针方法的想法,并且O(1)更新为MBo澄清的访问数组。这是一个使用哈希集实现唯一性的单指针想法,每次新的细分开始时都会清除该哈希集。
function f(A){
var sum = 0
var set = new Set
var len = 0
for (a of A){
if (sum >= 1000000000)
return 1000000000
if (set.has(a)){
sum += len*(len+1)/2
len = 1
set.clear()
} else {
len++
set.add(a)
}
}
sum += len*(len+1)/2
return Math.min(sum, 1000000000)
}
var A = [3, 4, 5, 5 ,2]
console.log(f(A))