Java 置换中的独立环
我在创建一个函数时遇到问题,该函数将置换作为输入,并打印出独立的循环(在循环表示法中)。 我将感谢任何帮助 输入:Java 置换中的独立环,java,c++,permutation,Java,C++,Permutation,我在创建一个函数时遇到问题,该函数将置换作为输入,并打印出独立的循环(在循环表示法中)。 我将感谢任何帮助 输入: 1 2 3 4 5 6 5 3 2 6 4 1 输出: (1 5 4 6)(2 3)从第一个数字(数字)开始,按照映射操作,直到返回到第一个数字。这是你的第一个周期 然后从下一个尚未访问的号码开始,并重复此过程 不断重复,直到访问完所有号码 ↓ 从第一个号码开始 1 2 3 4 5 6 1 5 3 2 6
1 2 3 4 5 6
5 3 2 6 4 1
输出:
(1 5 4 6)(2 3)
从第一个数字(数字)开始,按照映射操作,直到返回到第一个数字。这是你的第一个周期
然后从下一个尚未访问的号码开始,并重复此过程
不断重复,直到访问完所有号码
↓ 从第一个号码开始
1 2 3 4 5 6 1
5 3 2 6 4 1
* ↓ 1映射到5:
1 2 3 4 5 6 1 → 5.
5 3 2 6 4 1
* ↓ * 5张地图到4张:
1 2 3 4 5 6 1 → 5.→ 4.
5 3 2 6 4 1
* * * ↓ 4张地图到6张:
1 2 3 4 5 6 1 → 5.→ 4.→ 6.
5 3 2 6 4 1
****6映射到1:
1 2 3 4 5 6 1 → 5.→ 4.→ 6.→ 1.
5 3 2 6 4 1完成第一个循环
*↓ * * * 从第一个未访问的号码开始:
1 2 3 4 5 6 2
5 3 2 6 4 1
* * ↓ * * * 2到3的地图:
1 2 3 4 5 6 2 → 3.
5 3 2 6 4 1
****3映射到2:
1 2 3 4 5 6 2 → 3.→ 2.
5 3 2 6 4 1秒循环完成
访问的所有数字,结果:
1.→ 5.→ 4.→ 6和2→ 3.⇒ (1546)(23)
现在您只需要用您喜欢的语言编写代码
提示:您需要3个数组,一个用于第一组数字,一个用于第二组数字,以及一个用于跟踪访问过哪些数字的数组
您还需要一些东西来捕获结果,例如,如果您使用Java,则需要一个StringBuilder
更新 这是一个支持负数和多位数的Java解决方案,具有完整的输入验证:
private static String findCycles(int[] a, int[] b) {
if (a.length == 0)
throw new IllegalArgumentException("The sets cannot be empty");
if (a.length != b.length)
throw new IllegalArgumentException("Sets must have same size: " + a.length + " != " + b.length);
TreeMap<Integer, Integer> numIdx = IntStream.range(0, a.length).boxed()
.collect(Collectors.toMap(i -> a[i], Function.identity(),
(i1, i2) -> { throw new IllegalArgumentException("Duplicate numbers not allowed: " + a[i1]); },
TreeMap::new));
if (! IntStream.of(b).boxed().collect(Collectors.toSet()).equals(numIdx.keySet()))
throw new IllegalArgumentException("Sets must consist of the same numbers");
String separator = (numIdx.firstKey() < 0 || numIdx.lastKey() > 9 ? " " : "");
BitSet used = new BitSet(a.length);
StringBuilder result = new StringBuilder();
for (int idx; (idx = used.nextClearBit(0)) < a.length; ) {
StringJoiner cycle = new StringJoiner(separator, "(", ")");
do {
used.set(idx);
cycle.add(String.valueOf(a[idx]));
idx = numIdx.get(b[idx]);
} while (! used.get(idx));
result.append(cycle.toString());
}
return result.toString();
}
输出
(1546)(23)
(146837)(2)(5)
(14625837)
(1)(24)(3)
(-5 0 5)(10)(15 20)
> p>我将向您展示(许多)其中一个可能的解决方案和一个完整的C++实例。
我们只是沿着这两个排列的路径走。我们需要注意独立的循环,防止双循环,并需要避免无限循环通过循环
秘诀在于选择正确的容器类型。我用2。对于一个cyle,我使用了一个std::unordered\u集
。这只能包含唯一的元素。这样,就可以避免无限循环。例如:0,1,3,0,1,3,0,1,3。不可能,因为每个数字在容器中只能有一次。这将一次又一次地阻止排列。一旦我们看到一个已经在循环中的数字,我们就会停止
所有找到的循环将存储在第二个容器类型中:Astd::set
。std::set
也只能包含唯一的值,并且这些值是按顺序排列的
因为我们将复杂数据存储在std::set
中,所以我们为它创建了一个自定义比较器。我们需要注意std::set
不会包含2个双条目
在我们的例子中,double也是0,1,3和1,3,0。在我们的自定义比较器中,我们将首先将这两个集合复制到std::vector中,并对std::vector进行排序。这将使1,3,0变为0,1,3。这样我们就可以很容易地检测到替身
在下面的示例代码中,我总是只存储循环中第一次排列的值。第二个用作辅助对象,用于查找下一个要计算的值的索引
请参阅完整的工作示例:
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
#include <iterator>
#include <set>
// Make reading easier and define some alies names
using MyType = int;
using Cycle = std::unordered_set<MyType>;
using Permutation = std::vector<MyType>;
using Permutations = std::vector<Permutation>;
// We do not want to have double results.
// A double cyle is also a Cycle with elements in different order
// So define custom comparator functor for our resulting set
struct Comparator {
bool operator () (const Cycle& lhs, const Cycle& rhs) const {
// Convert the unordered_sets to vectors
std::vector<MyType> v1(lhs.begin(), lhs.end());
std::vector<MyType> v2(rhs.begin(), rhs.end());
// Sort them
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
// Compare them
return v1 < v2;
}
};
// Resulting cycles
using Cycles = std::set<Cycle, Comparator>;
int main() {
// The source data
Permutations perms2 = {
{1,2,3,4,5,6},
{5,3,2,6,4,1} };
// Lamda to find the index of a given number in the first permutation
auto findPos = [&perms2](const MyType& m) {return std::distance(perms2[0].begin(), std::find(perms2[0].begin(), perms2[0].end(), m)); };
// Here we will store our resulting set of cycles
Cycles resultingCycles{};
// Go through all single elements of the first permutation
for (size_t currentColumn = 0U; currentColumn < perms2[0].size(); ++currentColumn) {
// This is a temporary for a cycle that we found in this loop
Cycle trialCycle{};
// First value to start with
size_t startColumn = currentColumn;
// Follow the complete path through the 2 permutations
for (bool insertResult{ true }; insertResult; ) {
// Insert found element from the first permutation in the current cycle
const auto& [newElement, insertOk] = trialCycle.insert(perms2[0][startColumn]);
// Find the index of the element under the first value (from the 2nd permutation)
startColumn = findPos(perms2[1][startColumn]);
// Check if we should continue (Could we inster a further element in our current cycle)
insertResult = insertOk;
}
// We will only consider cycles with a length > 1
if (trialCycle.size() > 1) {
// Store the current temporary cycle as an additional result.
resultingCycles.insert(trialCycle);
}
}
// Show result. Simple output
std::cout << "\n\nFound Cycles:\n\n";
// Go through all found cycles
for (const Cycle& c : resultingCycles) {
// Print an opening brace
std::cout << "(";
// Handle the comma delimiter
std::string delimiter{};
// Print all integer values of the cycle
for (const MyType& m : c) {
std::cout << delimiter << m;
delimiter = ",";
}
std::cout << ")";
}
std::cout << "\n\n";
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
//使阅读更容易,并定义一些alies名称
使用MyType=int;
使用Cycle=std::无序_集;
使用置换=std::vector;
使用置换=std::vector;
//我们不希望出现双重结果。
//双循环也是元素顺序不同的循环
//因此,为我们的结果集定义自定义比较器函子
结构比较器{
布尔运算符()(常数循环和左、常数循环和右)常数{
//将无序的_集转换为向量
向量v1(lhs.begin(),lhs.end());
向量v2(rhs.begin(),rhs.end());
//分类
排序(v1.begin(),v1.end());
排序(v2.begin(),v2.end());
//比较它们
返回v11){
//将当前临时循环存储为附加结果。
结果周期。插入(三周期);
}
}
//显示结果。简单输出
大家好,非常感谢你们的解决方案,但我必须让它更简单。我应该使用2d dynamic
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
#include <iterator>
#include <set>
// Make reading easier and define some alies names
using MyType = int;
using Cycle = std::unordered_set<MyType>;
using Permutation = std::vector<MyType>;
using Permutations = std::vector<Permutation>;
// We do not want to have double results.
// A double cyle is also a Cycle with elements in different order
// So define custom comparator functor for our resulting set
struct Comparator {
bool operator () (const Cycle& lhs, const Cycle& rhs) const {
// Convert the unordered_sets to vectors
std::vector<MyType> v1(lhs.begin(), lhs.end());
std::vector<MyType> v2(rhs.begin(), rhs.end());
// Sort them
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
// Compare them
return v1 < v2;
}
};
// Resulting cycles
using Cycles = std::set<Cycle, Comparator>;
int main() {
// The source data
Permutations perms2 = {
{1,2,3,4,5,6},
{5,3,2,6,4,1} };
// Lamda to find the index of a given number in the first permutation
auto findPos = [&perms2](const MyType& m) {return std::distance(perms2[0].begin(), std::find(perms2[0].begin(), perms2[0].end(), m)); };
// Here we will store our resulting set of cycles
Cycles resultingCycles{};
// Go through all single elements of the first permutation
for (size_t currentColumn = 0U; currentColumn < perms2[0].size(); ++currentColumn) {
// This is a temporary for a cycle that we found in this loop
Cycle trialCycle{};
// First value to start with
size_t startColumn = currentColumn;
// Follow the complete path through the 2 permutations
for (bool insertResult{ true }; insertResult; ) {
// Insert found element from the first permutation in the current cycle
const auto& [newElement, insertOk] = trialCycle.insert(perms2[0][startColumn]);
// Find the index of the element under the first value (from the 2nd permutation)
startColumn = findPos(perms2[1][startColumn]);
// Check if we should continue (Could we inster a further element in our current cycle)
insertResult = insertOk;
}
// We will only consider cycles with a length > 1
if (trialCycle.size() > 1) {
// Store the current temporary cycle as an additional result.
resultingCycles.insert(trialCycle);
}
}
// Show result. Simple output
std::cout << "\n\nFound Cycles:\n\n";
// Go through all found cycles
for (const Cycle& c : resultingCycles) {
// Print an opening brace
std::cout << "(";
// Handle the comma delimiter
std::string delimiter{};
// Print all integer values of the cycle
for (const MyType& m : c) {
std::cout << delimiter << m;
delimiter = ",";
}
std::cout << ")";
}
std::cout << "\n\n";
return 0;
}