Мне нужно найти сдвиг двух циклических перестановок последовательностей.
ПРИМЕР:
3 5 1 2 4 35 7 8 1 2 5 9 4 7
5 7 8 1 2 5 9 4 73 5 1 2 4 3
Вторая последовательность является циклической перестановкой первой со сдвигом 6.
Мой алгоритм:
Например, я получаю следующую ошибку
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 15) >= this->size() (which is 15)
и если я попробую другие последовательности, результат будет неправильным.
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib>
int sequences_are_equal = 0;
bool sequences_have_same_elements(std::vector < int > a, std::vector < int > b) {
sequences_are_equal = 0;
if (a.size() != b.size())
return false;
for (int i = 0; i < a.size(); i++)
if (a.at(i) == b.at(i))
sequences_are_equal++;
if (sequences_are_equal == a.size()) return true;
sort(a.begin(), a.end());
sort(b.begin(), b.end());
for (int i = 0; i < a.size(); i++)
if (a.at(i) != b.at(i))
return false;
return true;
}
int CyclicPermutation(std::vector < int > a, std::vector < int > b) {
int shift = -1;
std::vector < int > temp(a.size(), 0);
std::vector < int > help(a.size(), 0);
if (sequences_have_same_elements(a, b)) {
int x = a.at(0);
a.erase(a.begin());
a.push_back(x);
temp.push_back(a.at(0));
temp.push_back(a.at(1));
for (int i = 0; i < b.size(); i++) {
help.push_back(b.at(i));
help.push_back(b.at(i + 1));
if (temp == help) {
shift = b.size() - i + 1;
break;
}
help.clear();
}
}
if (sequences_are_equal == a.size()) return 0;
return shift;
}
int main() {
int x;
std::vector < int > a, b;
std::cout << "First sequence: ";
while (std::cin >> x)
a.push_back(x);
std::cin.clear();
std::cin.ignore(1000, '\n');
std::cout << "Second sequence: ";
while (std::cin >> x)
b.push_back(x);
if (CyclicPermutation(a, b) == -1)
std::cout << "Second sequence is not cyclic permutaion of first.";
else
std::cout << "Second sequence is cyclic permutaion of first with shift " << CyclicPermutation(a, b) << ".";
return 0;
}
Не могли бы вы объяснить мне, где я допустил ошибку в своем алгоритме и коде? Как изменить это, чтобы работать правильно?
для последовательностей (1,2) и (2,1) он не дает исключения, он печатает просто неправильный результат
Ваш дизайн неправильный.
Кажется, вы просто хотите повернуть элементы в std::vector
.
Исключением является ошибка выхода за пределы: help.push_back(b.at(i + 1));
Странная обработка с "help" и "temp". Сначала вы создаете «help» и «temp» с n 0es в нем. Затем вы отталкиваете вещи, но только 2 элемента. Итак, если, например, исходный размер вектора равен 4, то ваши векторы будут 0,0,0,0,x,y.
Это довольно странно, или я этого не понимаю.
Что ты должен делать:
==
Вы можете либо использовать существующую функцию std::rotate
(см. здесь), либо написать простую функцию самостоятельно.
Вы можете изменить свою функцию следующим образом:
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits>
void rotateLeft(std::vector<int>& a) {
if (a.size() > 0) {
int tmp = a[0];
for (size_t k{}; k < a.size() - 1; ++k)
a[k] = a[k + 1];
a.back() = tmp;
}
}
int CyclicPermutation(std::vector<int>& a, std::vector<int>& b) {
// Set result to invalid
int result{ -1 };
int shiftCounter{};
// Only do something if the sizes are different
if (a.size() == b.size()) {
// Rotate until numbers are equal
while ((a != b) and (shiftCounter++ < a.size())) {
//std::rotate(a.begin(), a.begin() + 1, a.end());
rotateLeft(a);
}
if (shiftCounter < a.size())
result = shiftCounter;
}
return result;
}
int main() {
int x;
std::vector < int > a, b;
std::cout << "First sequence: ";
while (std::cin >> x)
a.push_back(x);
std::cin.clear();
std::cin.ignore(1000, '\n');
std::cout << "Second sequence: ";
while (std::cin >> x)
b.push_back(x);
int result = CyclicPermutation(a, b);
if (result < 0)
std::cout << "Second sequence is not cyclic permutaion of first.";
else
std::cout << "Second sequence is cyclic permutaion of first with shift " << result << ".";
return 0;
}
Редактировать:
Работает, см.
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits>
void rotateLeft(std::vector<int>& a) {
if (a.size() > 0) {
int tmp = a[0];
for (size_t k{}; k < a.size() - 1; ++k)
a[k] = a[k + 1];
a.back() = tmp;
}
}
int CyclicPermutation(std::vector<int>& a, std::vector<int>& b) {
// Set result to invalid
int result{ -1 };
int shiftCounter{};
// Only do something if the sizes are different
if (a.size() == b.size()) {
// Rotate until numbers are equal
while ((a != b) and (shiftCounter++ < a.size())) {
//std::rotate(a.begin(), a.begin() + 1, a.end());
rotateLeft(a);
}
if (shiftCounter < a.size())
result = shiftCounter;
}
return result;
}
int main() {
int x;
std::vector a{ 3, 5, 1, 2, 4, 3, 5, 7, 8, 1, 2, 5, 9, 4, 7 };
std::vector b{ 5, 7, 8, 1, 2, 5, 9, 4, 7, 3, 5, 1, 2, 4, 3 };
int result = CyclicPermutation(a, b);
if (result < 0)
std::cout << "Second sequence is not cyclic permutaion of first.";
else
std::cout << "Second sequence is cyclic permutaion of first with shift " << result << ".";
return 0;
}
Вы вводите рутину не хорошо, что. Вы должны знать, что ignore
— это функция неформатированного ввода.
Редактировать 2
Ваш ввод работает с исходной функцией:
например, он возвращает сдвиг как равный 0, что неверно
Это работает, пожалуйста, смотрите мое редактирование.
программа должна вводить элементы вектора до тех пор, пока не будет введено что-то, что не является числом, например first: 1 2 1 2 .
введите second: 2 1 2 1 abcde
не могли бы вы включить это в своем коде?
Ваш исходный код также работает с данным вводом. Можете ли вы сказать мне, с какой проблемой вы столкнулись?
Я не использовал result = CyclicPermutation(a, b);
, и из-за этого я получил 0 как сдвиг в (1,2,1,2), (2,1,2,1)... большое спасибо... это сработало...
просто правильное объявление вектора, оно должно быть std::vector<int>a{.....}
Я использую С++17. Здесь у нас есть CTAD. Затем вы можете опустить <int>
извините, я не знал, мы используем C++14
Что вы заметили, проходя код за строкой с помощью отладчика? Такие вещи, как
help.push_back(b.at(i + 1));
, скорее всего, вызовут такие исключения.