我有一个问题,让我们说:
从前一个生成一个新字符串 一个遵循一条规则。
1,11,21, 1211,111221,312211,13112221,......
这是我的解决方案:
#include <string>
#include <iostream>
using namespace std;
class look_n_say {
public:
look_n_say( int n ) : n( n ) {
}
friend ostream& operator <<( ostream& out, const look_n_say& rhs ) {
string result;
string init_str( "1" );
out << init_str << endl;
for( int i = 1; i < rhs.n; ++i ) {
result = rhs.get_new_str( init_str );
out << result << '\n';
init_str = result;
result.clear();
}
return out;
}
private:
string get_new_str( const string& str ) const {
int cnt( 1 );
string result;
for( string::size_type i = 0, len = str.length(); i < len; ++i ) {
if( i < len - 1 && str[i] == str[i + 1] ) {
++cnt;
}
else {
result.append( 1, cnt + 48 );
result.append( 1, str[i] );
cnt = 1;
}
}
return result;
}
private:
int n;
};
int main() {
look_n_say lns( 10 );
cout << lns << endl;
return 0;
}
我对我的解决方案不满意的原因是我错过了使用STL算法的优雅解决方案。我想到了std::transform
,但发现无法应用它。有没有更好的方法来解决这个问题?任何人都可以与我分享?任何有关我的编码风格的反馈和评论将不胜感激!请告诉我我的编码风格有多糟糕,我将从中学习。
谢谢,
陈
答案 0 :(得分:2)
据我所知,没有可以生成此序列的STL“单行”。您可以使用算法组合来尝试描绘相邻连续值的所有范围,可能使用std::adjacent_difference
,但老实说,我认为手写循环会更优雅。
在一个不相关的说明中,我不确定我是否支持你设计look_n_say
的决定。在编写类时,您有一个对象,其唯一目的是将值写入ostream
。您无法查询系列中的各个值,也无法更改在创建对象后获得的值的数量。每次拨打n
时,您也会急切地重新计算第一个operator <<
号码,这可能效率极低。我建议将班级改为:
n
。一种可能的设计可能是这样的:
class LookAndSaySeries {
public:
string getTerm(size_t index) const; // Get the appropriate term of the series.
private:
/* Previously-retrieved values, marked mutable since getTerm() will modify even
* though it's a semantically-const operation.
*/
mutable vector<string> cachedValues; // Values you've handed back before.
void generateNext() const;
};
string LookAndSaySeries::getTerm(size_t index) const {
/* Keep generating values until you have enough to satisfy the request. */
while (index >= cachedValues.size())
generateNext();
return cachedValues[index];
}
void LookAndSaySeries::generateNext() const {
/* ... insert logic here to generate next term ... */
cachedValues.push_back(/* ... that value ... */);
}
这使您可以轻松查询单个数字,而无需在每次迭代时重新计算它们。您仍然可以像以前一样将值打印到流中,但现在可以更精细地控制数字的生成方式。
答案 1 :(得分:0)
此算法中的单个步骤实际上将run-length encoding应用于先前的序列。在Rosetta Stone上有几种RLE解决方案,包括一种用于C ++的解决方案。也许这值得一瞥。
但是,该解决方案也不使用任何花哨的标准库算法。
答案 2 :(得分:0)
Fancy-pants STL方法:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
typedef std::vector<int> T;
void thingy(const T &v, const int n)
{
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ""));
std::cout << std::endl;
if (n > 0)
{
T w;
for (T::const_iterator it = v.begin(); it != v.end(); )
{
T::const_iterator it2 = std::find_if(it, v.end(),
std::bind1st(std::not_equal_to<int>(), *it));
w.push_back(std::distance(it, it2));
w.push_back(*it);
it = it2;
}
thingy(w, n-1);
}
}
int main()
{
T v;
v.push_back(1);
thingy(v, 5);
}