计算不同切片的数量(仅包含唯一编号)

时间:2019-09-02 16:09:01

标签: java arrays algorithm

我解决了以下提供的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;
    }

但是,在线法官估计正确性和性能较低。我该如何改善?

2 个答案:

答案 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))