正如 SergeyA 提议的那样。我们首先尝试理解问题,然后逐步解决。然后我们编写代码。好的。
所以,前几天,我正在解决交给你的问题。
- 首先,我们有一个包含随机字符“R”、“B”、“G”的字符串。
- 然后我们有 RGBRGBRGB 的序列...
- 我们想找到一个给定长度的子字符串
- 我们必须找到 RGBRGBRGB... 字符串的子字符串
- 然后我们需要将其与随机字符串进行比较,并检查随机字符串中某个位置的最小必要字符更改(或最大相同字符)
从 4. 我们了解到,结果必须是 RGBRGBRGB... 字符串的子字符串。所以我们正在寻找一个 RGBRGBRGB... 部分。这是解决问题的关键。
由于子字符串可以在 RGBRGBRGB 中的任何位置开始...如果我们不知道 RGB 的周期性重复,我们将需要做很多工作。所以,我们需要找到一个 RGBRGBRGB...、GBRGBRGB... 或 BRGBRGB... 的子字符串,子字符串长度为 k。
所以我们计划进行 3 次比较运行,分别为 1.RGBRGBRGB...、2.GBRGBRGB...和 3.BRGBRGB...
接下来,我们执行一个循环,比较随机字符源字符串中的 k 个元素,并将其与其中一个周期性字符串进行比较。我们将从位置 1 开始,然后是位置 2,依此类推。
当我们进行了至少 k 次比较时,我们计算相等字符的总和。如果这个和大于前一个,那么我们找到了一个新的最大值并将其存储。
等等等等。
复杂度大约是 3*sizeof(input string)
我只需要一些额外的内存用于计数器(计数:sizeof 子字符串长度)。
请查看大约 35 行代码。到目前为止我还没有优化。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
constexpr size_t SubStringSize = 6U;
const std::string testInput{ "RRRGBGBGGGBBRRRBGGBRGBGRRRGBBGRGGBBGRRBGRBBGGRGRGRGGRBRBGRRBGRGGBBGGBGBGBBBGGBBRBBRGRGGBRRR" };
const std::string rgbSourceCharacters("RGBRG");
inline char getRGB(size_t shift, size_t offset)
{
return rgbSourceCharacters[shift + offset % 3U];
}
int main()
{
// Some test string
const size_t size = testInput.size();
// Delta between Strings with RGBRGBRGB..... and testInput String
std::vector<size_t> delta(SubStringSize);
// This is the number of maxEquals for the given SubString Size
size_t maxEquals{ 0U };
// Position of char of best fitting substring
size_t lastMaxEqualsPos{ 0U };
// Which rgb sequence corresponds to ´best fitting substring
size_t rgbShiftForMax{ 0U };
// Check all possible RGB sequences, RGBRGBRGB... , GBRGBRGB..., BRGBRGB...
for (size_t i = 0U; i < 3U; ++i)
{
// Set all values of our counters to 0
std::fill(delta.begin(), delta.end(), 0U);
// We will always begin with writing to the first position of the delta vector
size_t indexInDeltaVector{ 0U };
// Iterate over all characters of the source string
for (size_t k = 0U; k < size; ++k)
{
// Check if the character is equal to RGB sequence, RGBRGBRGB... , GBRGBRGB..., BRGBRGB...
delta[indexInDeltaVector] = (testInput[k] == getRGB(i,k)) ? 1U : 0U;
// Increment index in delta vector, only until last position. Then stop
if (indexInDeltaVector < (SubStringSize - 1U))
++indexInDeltaVector;
// If we compared enough values
else {
// Calculate the sum of the previous n comparisons
const size_t sum = std::accumulate(delta.begin(), delta.end(), 0U);
// Check, if we found a new maximum
if (sum > maxEquals) {
// If so then store relevant data
maxEquals = sum;
lastMaxEqualsPos = k - SubStringSize + 1U;
rgbShiftForMax = i;
}
// Make space for nect comparison
std::rotate(delta.begin(), delta.begin() + 1U, delta.end());
}
}
}
// Show result
std::cout << "\n\nFinal Result\n\nSource String:\n\n" << "0123456789012345678901234567890123456789012345678901234567890\n" << testInput
<< "\n\nSubstring Length: " << SubStringSize
<< "\nMax Equals: " << maxEquals
<< "\nTo be changed: " << SubStringSize - maxEquals
<< "\n\nSub String at pos: " << lastMaxEqualsPos
<< "\n\n--> " << testInput.substr(lastMaxEqualsPos, SubStringSize)
<< "\n--> ";
for (size_t offset = lastMaxEqualsPos; offset < lastMaxEqualsPos + SubStringSize; ++offset)
std::cout << getRGB(rgbShiftForMax, offset);
std::cout << '\n';
return 0;
}
第一轮优化。将代码的功能行数减少到 ~20 行:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
constexpr size_t SubStringSize = 6U;
constexpr std::string_view testInput{ "RRRGBGBGGGBBRRRBGGBRGBGRRRGBBGRGGBBGRRBGRBBGGRGRGRGGRBRBGRRBGRGGBBGGBGBGBBBGGBBRBBRGRGGBRRR" };
int main()
{
// Delta between Strings with RGBRGBRGB..... and testInput String
std::vector<size_t> delta(SubStringSize);
// This is the result, the number of minDifferences for the given SubString Size
size_t minDifference{ SubStringSize };
// Check all possible RGB sequences, RGBRGBRGB... , GBRGBRGB..., BRGBRGB...
for (size_t i = 0U; i < 3U; ++i)
{
// Set all values of our counters to 0
std::fill(delta.begin(), delta.end(), 0U);
// We will always begin with writing to the first position of the delta vector
size_t indexInDeltaVector{ 0U };
// Iterate over all characters of the source string
for (size_t k = 0U; k < testInput.size(); ++k) {
// Check, if the char is equal to RGB sequence, RGBRGBRGB... , GBRGBRGB..., BRGBRGB...
delta[indexInDeltaVector] = (testInput[k] == "RGBRG"[k % 3U + i]) ? 0U : 1U;
// Increment index in delta vector, only until last position. Then stop
if (indexInDeltaVector < (SubStringSize - 1U))
++indexInDeltaVector;
// If we compared enough values
else {
// Calculate the sum of the previous n comparisons
const size_t sum = std::accumulate(delta.begin(), delta.end(), 0U);
// Check, if we found a new minimum
if (sum < minDifference)
// If so then store relevant data
minDifference = sum;
// Make space for next comparison
std::rotate(delta.begin(), delta.begin() + 1U, delta.end());
}
}
}
// Show result
std::cout << "\n\nFinal Result. Minimum characters to be changed: " << minDifference << '\n';
return 0;
}