【问题标题】:Removing duplicates from a sorted array in c++从 C++ 中的排序数组中删除重复项
【发布时间】:2021-12-12 01:54:47
【问题描述】:

我正在尝试从已排序的数组中删除重复项。代码为一个测试用例提供了正确的输出,但未能为多个测试用例提供正确的输出。我用其他方法得到了正确的输出,但这种方法有什么问题?我该如何解决这个问题?

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int main() {
    // your code goes here
    int t;
    cin>>t;
    
    while(t--){
    
    int n;
    cin>>n;
    int a[n],i,k,temp,count;
    
    for(i=0;i<n;i++){
        cin>>a[i];
    }
    
    sort(a,a+n);
   
    count=0;
    for(i=0;i<n;i++){
        
        if(a[i-1]-a[i]==0){
            
            temp = a[i];
            count++;
            for(k=i;k<n;k++){
                a[k] = a[k+1];  
            }
            
        }   
    }
    
    for(i=0;i<n-count;i++){
        cout<<a[i]<<" ";
    }
    cout<<endl;
    
        
    }
    
}

【问题讨论】:

标签: c++ algorithm sorting for-loop duplicates


【解决方案1】:

这样的变长数组

int a[n],i,k,temp,count;

不是标准的 C++ 功能。相反,您应该使用标准容器std::vector&lt;int&gt;

这个 if 语句

if(a[i-1]-a[i]==0){

由于表达式 a[i-1] 而在 i 等于 0 时调用未定义的行为。

这个for循环也存在同样的问题

        for(k=i;k<n;k++){
            a[k] = a[k+1];  
        }

k 等于n - 1 由于表达式a[k+1]

此外,每次找到重复元素后复制所有元素的效率也很低。

请注意,可以使用标准算法std::unique 代替您的循环。

如果要使用 for 循环,那么您可以实现类似以下的内容

#include <iostream>

int main() 
{
    int a[] = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
    const size_t N = sizeof( a ) / sizeof( *a );
    
    size_t n = 0;
    
    for ( size_t i = 0; i < N; i++ )
    {
        if ( i == 0 || a[i] != a[n-1] )
        {
            if ( i != n  ) a[n] = a[i];
            ++n;
        }
    }
    
    for ( size_t i = 0; i < n; i++ )
    {
        std::cout << a[i] << ' ';
    }
    std::cout << '\n';
    
    return 0;
}

程序输出是

1 2 3 4 5 

如果使用标准算法std::unique,那么解决方案会更简单,因为不需要自己编写for循环。

#include <iostream>
#include <iterator>
#include <algorithm>

int main() 
{
    int a[] = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };

    auto last = std::unique( std::begin( a ), std::end( a ) );
    
    for ( auto first = std::begin( a ); first != last; ++first )
    {
        std::cout << *first << ' ';
    }
    std::cout << '\n';
    
    return 0;
}

程序输出和上图一样就是

1 2 3 4 5 

【讨论】:

    【解决方案2】:

    我发现您的代码有两个主要问题,都是从数组中越界读取:

    if(a[i-1]-a[i]==0) 将在某一时刻被i==0 调用,访问元素a[-1]

    这里:

    for(k=i;k<n;k++){
       a[k] = a[k+1];  
    }
    

    在最后一次循环迭代中,当k == n-1数组元素a[n]被访问时,也是越界访问。

    【讨论】:

      猜你喜欢
      • 2016-10-01
      • 2013-09-26
      • 2021-11-12
      • 2021-01-27
      • 2016-01-24
      • 2022-01-03
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多