如何在数字列表中查找某个数字列表的位置

时间:2014-09-26 13:36:44

标签: c++ algorithm

假设我有一个数字列表:[0 0 1 1 1 0 1 1 0 1 0 0 0 1 1],它由0或1组成,我的问题是如何在列表中找到数字1的开始和结束位置。以上面的数字列表为例,1列表的位置为:

[2 4]
[6 7]
[9 9]
[13 14]

使用C ++,实现了以下方法:

int main()
{   

    unsigned char charArray[15]={0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1};

    std::vector<std::pair<int,int> > posArray;

    int begPos=-1;
    int endPos=-1;
    for(int i=0; i<15; i++)
    {
        if(charArray[i] ==1)
        {
            if(begPos!=-1)
            {
                endPos++;
            }
            else
            {
                begPos=i;
                endPos=i;
            }
        }
        else
        {
            if(begPos != -1)
            {
                posArray.push_back(std::make_pair<int,int>(begPos,endPos));
                begPos=-1;
            }

        }

    }
    if(charArray[14] == 1)
    {
        posArray.push_back(std::make_pair<int,int>(begPos,endPos));
    }

    for(int i=0; i<posArray.size(); i++)
    {
        std::cout<<"( "<<posArray[i].first<<" , "<<posArray[i].second<<" )"<<std::endl;
    }
    return 0;
}

这个问题是否有更有效的解决方案(时间或空间)?谢谢。

2 个答案:

答案 0 :(得分:4)

我建议的解决方案效率不高但看起来更好。:)

尝试以下

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <utility>
#include <functional>

int main() 
{
    unsigned char charArray[] = 
    { 
        0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1
    };
    std::vector<std::pair<int,int> > posArray;

    auto first = std::begin( charArray );

    while ( ( first = std::find( first, std::end( charArray ), 1 ) ) != std::end( charArray) )
    {
        auto last = std::find_if( first, std::end( charArray ), 
                                  std::bind2nd( std::not_equal_to<int>(), 1 ) );

        posArray.push_back( { std::distance( charArray, first ),
                              std::distance( charArray, last ) - 1 } );
        first = last;                             
    }

    for ( auto &p : posArray ) std::cout << '[' << p.first 
                                         << ' ' << p.second
                                         << ']' << std::endl;

    return 0;
}

输出

[2 4]
[6 7]
[9 9]
[13 14]

如果数组仅包含0和1,那么您可以替换此语句

    auto last = std::find_if( first, std::end( charArray ), 
                              std::bind2nd( std::not_equal_to<int>(), 1 ) );

这个

    auto last = std::find( first, std::end( charArray ), 0 );

在这种情况下,循环看起来像

while ( ( first = std::find( first, std::end( charArray ), 1 ) ) != std::end( charArray) )
{
    auto last = std::find( first, std::end( charArray ), 0 ); 

    posArray.push_back( { std::distance( charArray, first ),
                          std::distance( charArray, last ) - 1 } );
    first = last;                             
}

要编写更高效的代码,必须为向量保留内存。

例如

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <utility>
#include <functional>

int main() 
{
    unsigned char charArray[] = 
    { 
        0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1
    };
    std::vector<std::pair<int,int> > posArray;

    size_t n = std::inner_product( std::next( std::begin( charArray ) ), 
                                   std::end( charArray ), 
                                   std::begin( charArray ), 
                                   0ul, 
                                   std::plus<size_t>(),
                                   std::greater<char>() );

   n += charArray[0] == 1;

    posArray.reserve( n );

    auto first = std::begin( charArray );

    while ( ( first = std::find( first, std::end( charArray ), 1 ) ) != std::end( charArray) )
    {
        auto last = std::find( first, std::end( charArray ), 0 ); 

        posArray.push_back( { std::distance( charArray, first ),
                              std::distance( charArray, last ) - 1 } );
        first = last;                             
    }

    for ( auto &p : posArray ) std::cout << '[' << p.first 
                                         << ' ' << p.second
                                         << ']' << std::endl;

    return 0;
}

答案 1 :(得分:1)

无法抗拒。这是我的两个问题:

int main()
{
    unsigned char charArray[] = {0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1};

    std::vector<std::pair<int,int> > posArray;

    size_t found[2];
    unsigned char seek = 0;

    for(size_t i = 0; i < sizeof(charArray); ++i)
    {
        if(seek == charArray[i])
            continue;

        found[seek] = i - seek;

        if(!(seek ^= 1))
            posArray.push_back(std::make_pair(found[0], found[1]));
    }

    if(seek)
        posArray.push_back(std::make_pair(found[0], sizeof(charArray) - 1));

    for(int i = 0; i < posArray.size(); i++)
        std::cout << "[" << posArray[i].first
            << " , " << posArray[i].second << "]" << '\n';
}

<强>输出

[2 , 4]
[6 , 7]
[9 , 9]
[13 , 14]