在数组中计数不同的切片

count distinct slices in an array

本文关键字:切片 数组      更新时间:2023-10-16

我试图解决这个问题。

整数m和一个非空的零索引阵列由n组成 给出了非阴性整数。阵列A中的所有整数都少于 或等于m。

一对整数(P,Q),因此0≤p≤Q<n,称为切片 Array A的A.切片由a [p],a [p 1],...,...的元素组成 一个[q]。一个独特的切片是仅由唯一数字组成的切片。 也就是说,在切片中没有一个以上的单个数字发生。

例如,考虑整数m = 6和数组a,以便:

A[0] = 3
A[1] = 4
A[2] = 5
A[3] = 5
A[4] = 2 

完全有九个不同的切片:(0,0),(0,1),(0,2),(1, 1),(1,2),(2,2),(3,3),(3,4)和(4,4)。

目标是计算不同切片的数量。

预先感谢。

#include <algorithm>
#include <cstring>
#include <cmath>
#define MAX 100002
// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;
using namespace std;
bool check[MAX];
int solution(int M, vector<int> &A) {
    memset(check, false, sizeof(check));
    int base = 0;
    int fibot = 0;
    int sum = 0;
    while(fibot < A.size()){
        if(check[A[fibot]]){
            base = fibot;
        }
        check[A[fibot]] = true;
   sum += fibot - base + 1;
        fibot += 1;  
    }
    return min(sum, 1000000000);
}

解决方案是不正确的,因为您的算法是错误的。

首先,让我向您展示一个反示例。令A = {2, 1, 2}。第一次迭代:base = 0fibot = 0sum += 1.是正确的。第二个:base = 0, fibot = 1sum += 2。这也是正确的。最后一步:fibot = 2check[A[fibot]] is true,因此,base = 2。但这应该是1。因此,您的代码在正确答案1 + 2 + 2 = 5时返回1 + 2 + 1 = 4

正确的方法可能就是这样:从L = 0开始。对于从0n - 1的每个R,请继续向右移动L,直到subarray Contais只有不同的值(您可以将每个值的出现数量保持在数组中,并使用A[R]是唯一可以发生更多元素的事实比一次)。

您的代码还有一个问题:如果int在测试平台上为32位类型,则sum变量可能会溢出(例如,如果A的所有元素都不同,则可以溢出。

至于为什么您的算法不正确的问题,我不知道为什么首先应该正确。你能证明这个吗?base = fibot分配对我来说很随意。

我想分享我在C 中实现的算法的解释,然后是实际实施。

  1. 请注意,不同切片的最小量为n,因为每个元素都是一个独特的单项切片。
  2. 从第一个元素启动背部索引。
  3. 从第一个元素开始前索引。
  4. 前进前面,直到我们在序列中找到重复。
  5. 在每次迭代中,用必要的数量增加计数器,这是前后的差异。
  6. 如果我们在任何迭代时达到最大计数,只需立即返回以进行轻微优化。
  7. 在序列的每次迭代中,记录发生的元素。
  8. 一旦我们找到了副本,请在重复的前方提出背部索引。
  9. 当我们推进背部索引时,清除所有发生的元素,因为我们启动了一个超出这些元素的新切片。

此解决方案的运行时复杂性是O(N),因为我们遍历每个
元素。

该解决方案的空间复杂性是O(M),因为我们有一个哈希这些发生在序列中的元素。该哈希的最大元素是m。

int solution(int M, vector<int> &A)                                             
{                                                                               
  int N = A.size();                                                             
  int distinct_slices = N;                                                      
  vector<bool> seq_hash(M + 1, false);                                          
  for (int back = 0, front = 0; front < N; ++back) {                            
    while (front < N and !seq_hash[A[front]]) { distinct_slices += front - back; if (distinct_slices > 1000000000) return 1000000000; seq_hash[A[front++]] = true; }
    while (front < N and back < N and A[back] != A[front]) seq_hash[A[back++]] = false;
    seq_hash[A[back]] = false;                                                  
  }                                                                             
                                                                                
  return distinct_slices;                                                       
}

100%python解决方案,感谢https://www.martinkysel.com/coditility-countdistiincle-countdistinctslices-solate/

def solution(M, A):
    
        the_sum = 0
    
        front = back = 0
    
        seen = [False] * (M+1)
    
        while (front < len(A) and back < len(A)):
    
            while (front < len(A) and seen[A[front]] != True):
    
                the_sum += (front-back+1)
    
                seen[A[front]] = True
    
                front += 1
    
            else:
    
                while front < len(A) and back < len(A) and A[back] != A[front]:
    
                    seen[A[back]] = False
    
                    back += 1
    
                seen[A[back]] = False
    
                back += 1
                   
        return min(the_sum, 1000000000)  
           

使用Ruby

100%的解决方案
LIMIT = 1_000_000_000
def solution(_m, a)
  a.each_with_index.inject([0, {}]) do |(result, slice), (back, i)|
    return LIMIT if result >= LIMIT
    slice[back] = true
    a[(i + slice.size)..-1].each do |front|
      break if slice[front]
      slice[front] = true
    end
    slice.delete back
    [result + slice.size, slice]
  end.first + a.size
end

使用Caterpillar算法和S(n+1) = S(n) + n + 1的公式,其中S(n)n-元素数Java解决方案的切片计数:

 public int solution(int top, int[] numbers) {
        int len = numbers.length;
        long count = 0;
        if (len == 1) return 1;
        int front = 0;
        int[] counter = new int[top + 1];
        for (int i = 0; i < len; i++) {
            while(front < len && counter[numbers[front]] == 0 ) {
                count += front - i + 1;
                counter[numbers[front++]] = 1;
            }
            while(front < len && numbers[i] != numbers[front] && i < front) {
                counter[numbers[i++]] = 0;
            }
            counter[numbers[i]] = 0;
            if (count > 1_000_000_000) {
                return 1_000_000_000;
            }
        }
        return count;
    }