【问题标题】:Work out a solution for codality?想出一个解决方案?
【发布时间】:2015-03-20 10:58:55
【问题描述】:

给出了一个由 N 个不同整数组成的零索引数组 A。该数组包含[1..(N + 1)] 范围内的整数,这意味着缺少一个元素。

你的目标是找到那个缺失的元素。

写一个函数:

int solution(int A[], int N); 

给定一个零索引数组A,返回缺失元素的值。

例如,给定数组 A 使得:

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

函数应该返回4,因为它是缺少的元素。

假设:

N is an integer within the range [0..100,000];
the elements of A are all distinct;
each element of array A is an integer within the range [1..(N + 1)].

复杂性:

expected worst-case time complexity is O(N);
expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).

它不适用于有两个元素的情况

int solution(vector<int> &A) {

    sort(A.begin(), A.end());
    int missingIndex = 0;

    for (int i = 0; i < A.size(); i++)
    {
        if ( i != A[i]-1)
        {
            missingIndex = i+1;
        }

    }
    return missingIndex;
}

【问题讨论】:

  • 使用排序将导致不具有所需的最坏情况时间复杂度 O(N)。你必须做一些比这更聪明的事情。就像从元素 1 (A[0]) 开始,获取它的值 (2),到元素 2 (A[1]),将其标记为“已看到”(例如,通过赋予它值 0),对 A 执行相同操作[1]。完成所有这些,扫描阵列并找到未标记为已见的阵列。在时间上应该是 O(n),在空间上应该是 O(1),代价是搞砸了原始数据。不错的谜题,但我现在不想写代码。
  • @ecotax 在这种情况下,排序可以达到O(N) 的复杂性。由于您的值范围有限,因此它适用于计数排序。真正的限制是O(1) 空间限制:)
  • @fjardon 确实,在这种情况下,您可以使用足够高效的排序算法。此外,Raistmaj 找到了一个更简单/更智能的解决方案。不错。

标签: c++ algorithm


【解决方案1】:

由于您的数组是零索引的,并且数字是从 1 到 N+1,因此语句应该是:

if ( i != A[i]-1)

此外,您应该在更新 missingIndex 后立即退出 for 循环,因为缺失元素之外的所有条目都应具有 (i != A[i]-1)

此外,由于排序您的解决方案是 O(NlogN) 而不是 O(N)。

相反,您可以将数组(using unsigned long long int) 中的所有元素相加,并检查它与N(N+1)/2 的差异

【讨论】:

  • 仍然没有通过测试用例,对于单个元素和数组中的两个元素
  • 检查它与 N(N+1)/2 的差异非常棒!
  • 还是这个错误, if ( i != A[i]-1) { missingIndex = i+1;休息; }
  • int 解决方案(vector &A) { sort(A.begin(), A.end()); int 缺失索引 = 0; for (int i = 0; i
  • 元素的总和是正确的答案,不要排序或任何东西,只需计算总和并用实际值减去它,是 O(n) 和 O(1)。几年前我做过这个测试。恕我直言,为了测试程序员的技能,Codality 是公司可以做的最糟糕的事情之一,仍然有很多“大”公司使用它。
【解决方案2】:

您可以使用arithmetic progression 的简单数学公式来获得从 1 到 N+1 的所有数字的总和。然后遍历所有给定的数字并计算总和。缺少的元素将是两个总和之间的差。

int solution(std::vector<int> &a) {
    uint64_t sum = (a.size() +1 ) * (a.size() + 2) / 2;
    uint64_t actual = 0;
    for(int element : a) {
        actual += element;
    }
    return static_cast<int>(sum - actual);
}

【讨论】:

  • 我可以得到你的联系方式,我也是住在奥地利的移民 :) ?
【解决方案3】:

充分利用 STL 的力量:

#include <algorithm>
#include <functional>

int solution(vector<int> &A) {
    return std::accumulate(A.begin(), A.end(), (A.size()+1) * (A.size()+2) / 2, std::minus<int>());
}

【讨论】:

    【解决方案4】:

    此解决方案使用值的符号作为标志。它最多需要两次通过元素。 N(N+1)/2 解决方案只需要通过一次。

    int solution(vector<int> &a) {
        int n = (int)a.size();
        for(auto k : a)
        {
            int i = abs(k) - 1;
            if (i != n)
                a[i] = -a[i];
        }
    
        for (int i = 0; i < n; ++i)
            if (a[i]>0)
                return i+1;
        return n+1;
    }
    

    【讨论】:

      【解决方案5】:

      我以这种方式解决了它,并考虑将其发布在这里,以供我自己和其他人参考:)

      #include <cstdint>
      #include <numeric>
      int solution(vector<int> &A) {
         uint64_t sumAll = (A.size() + 1) * (A.size() + 2) / 2;
         uint64_t sumA = std::accumulate(A.begin(), A.end(), 0);
         return sumAll- sumA;
      }
      

      【讨论】:

        【解决方案6】:

        我用这个解决方案解决了它,也许有更好的东西,但我用不同的值测试它,发现它工作正常,而其他解决方案给我的结果很奇怪。 例如:

        std::vector<int> A = { 12,13,11,14,16 };
        std::vector<int> A2 = { 112,113,111,114,116 };
        
        
        int  Solution(std::vector<int> &A)
        {
        int temp;
        for (int i = 0; i < A.size(); ++i)
        {
            for (int j = i+1;j< A.size();++j )  
        {
            if (A[i] > A[j])
                {
                    temp = A[i];
                    A[i] = A[j];
                    A[j] = temp;
                }
            }
        }
        
        for (int i = 0; i < A.size()-1;++i)
        {
            if ((A[i] + 1 != A[i + 1]))
            {
            return (A[i] + 1);
            }
            if(i+1 == A.size() - 1)
            return (A[i+1] + 1);
        
        }}
        

        现在一切正常,但如果我使用上面的数组和下面的方法,我会得到错误的值,除了小数字

         std::vector<int> A = { 12,13,11,14,16 };
         int Solution_2(std::vector<int> &A) 
        {
        unsigned int n = A.size() + 1;
        long long int estimated = n * (n + 1) / 2;
        long long int total = 0;
        for (unsigned int i = 0; i < n - 1; i++) total += A[i];
        return estimated - total;
        }
        

        我会得到这个结果 -45。

        如果我使用数组 A,这个结果也是一样的:

        std::vector<int> A = { 12,13,11,14,16 };
        int Solution_3(std::vector<int> &A) 
        {
         uint64_t sumAll = (A.size() + 1) * (A.size() + 2) / 2;
         uint64_t sumA = std::accumulate(A.begin(), A.end(), 0);
         return sumAll - sumA;
        }
        

        希望有人解释为什么会发生这种情况。

        【讨论】:

          猜你喜欢
          • 2012-03-31
          • 2011-03-23
          • 2021-05-20
          • 1970-01-01
          • 2022-06-12
          • 2011-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多