C++ 如何在另一个未排序数组中找到一个未排序数组元素的不同索引?
有两个字符数组。这两个数组大小相同,形式混乱 例如:C++ 如何在另一个未排序数组中找到一个未排序数组元素的不同索引?,c++,arrays,time-complexity,C++,Arrays,Time Complexity,有两个字符数组。这两个数组大小相同,形式混乱 例如: char a[] = {'a', 'b', 'a', 'b', 'c', 'a', 'b', 'a', 'b', 'c' }; char b[] = {'a', 'a', 'b', 'b', 'c', 'c', 'b', 'b', 'a', 'a' }; 我想找到数组a中数组b元素的不同位置(基于1的索引),在本例中是:1,3,2,4,5,10,7,9,6,8 我实现了以下暴力方法,即O(n2): for(int i=0;i是索引,第二个代
char a[] = {'a', 'b', 'a', 'b', 'c', 'a', 'b', 'a', 'b', 'c' };
char b[] = {'a', 'a', 'b', 'b', 'c', 'c', 'b', 'b', 'a', 'a' };
我想找到数组a中数组b元素的不同位置(基于1的索引),在本例中是:1,3,2,4,5,10,7,9,6,8
我实现了以下暴力方法,即O(n2):
for(int i=0;i cout您可以有一个哈希表,每个bucket中都有一个列表。该列表将包含字符所在的b[]索引
取b[]中的每个元素,比如b[i],在哈希表中找到索引等于b[i]的列表(在本例中为“a”或“b”或“c”)。如果没有列表,则创建一个值为i+1的列表。如果找到列表,则将i+1添加到列表末尾
在您的示例中,插入完成后
- “a”将是列表1、2、9、10
- “b”将是列表3、4、7、8
- “c”将是列表5,6
在处理条目时,使用列表中的第一个元素并从列表中删除第一个元素。
在上面的例子中
处理完第一个条目“a”后,您将给出1,并从索引“a”处的列表中删除1。现在
- “a”将是列表2、9、10
- “b”将是列表3、4、7、8
- “c”将是列表5,6
处理完第二个条目“b”后,您将给出3,并从索引“b”处的列表中删除3。现在
- “a”将是列表2、9、10
- “b”将是列表4、7、8
- “c”将是列表5,6
这将是O(N)?(假设您有双链接列表)编辑
与我的答案相比,我更喜欢@user207933的答案。相同的概念,更容易实现
反向查找的具体实现。您将看到前两个循环是开销。unordered_map
基本上是另一个答案中建议的“哈希表”
<代码>自动IT >代码是一个迭代器,其中<代码>第一个/代码>是索引,第二个代码>第二个/代码>是值(A<代码>队列<代码>,在我们的例子中)。这使得混淆是反向查找,“索引”也是您所考虑的值(反之亦然),队列中的每个“值”是一个索引为“代码> A<代码> < < /P>
我使用队列是因为您只想使用每个索引一次(因此
pop
相当于将值设置为\0
)
不过,我认为理解它的最好方法是在调试器中逐步完成它
#include <unordered_map>
#include <queue>
#include <memory>
#include <iostream>
using namespace std;
int main()
{
char a[] = { 'a', 'b', 'a', 'b', 'c', 'a', 'b', 'a', 'b', 'c' };
char b[] = { 'a', 'a', 'b', 'b', 'c', 'c', 'b', 'b', 'a', 'a' };
unordered_map<char, shared_ptr<queue<int>>> reverseIndex;
//create a queue for each unique char
for (int i = 0; i < 10; ++i)
{
auto it = reverseIndex.find(a[i]);
if (it == reverseIndex.end())
{
reverseIndex.emplace(a[i], make_shared<queue<int>>());
}
}
//put the indexes as *values* into our unordered_map vectors
for (int i = 0; i < 10; ++i)
{
auto it = reverseIndex.find(a[i]);
it->second->push(i);
}
//perform the actual work
for (int i = 0; i < 10; ++i)
{
auto it = reverseIndex.find(b[i]);
cout << it->second->front()+1 << "\n";
//you'll need to push the value back onto the queue for multiple uses of reverseIndex: it->second->push(it->second->front());
it->second->pop();
}
return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
字符a[]={'a','b','a','b','c','a','b','a','b','c'};
字符b[]={'a','a','b','b','c','c','b','b','a','a'};
无序地图反向索引;
//为每个唯一字符创建一个队列
对于(int i=0;i<10;++i)
{
auto it=reverseIndex.find(a[i]);
if(it==reverseIndex.end())
{
放置(a[i],make_shared());
}
}
//将索引作为*值*放入无序的映射向量中
对于(int i=0;i<10;++i)
{
auto it=reverseIndex.find(a[i]);
it->second->push(一);
}
//执行实际工作
对于(int i=0;i<10;++i)
{
autoit=reverseIndex.find(b[i]);
cout second->front()+1它可以以O(n)内存为代价减少到O(n)时间
您应该创建二维数组。它的第一个维度将由所有字符组成(总共256个=2^8个索引,因为sizeof(char)=1字节),第二个维度将超过数组的n个元素
所以,如果你有
char a[n] = ...;
char b[n] = ...;
你应该分配
int c[256][n]; // O(n) memory
int s[256]; // O(1) memory
int e[256]; // O(1) memory
并用零填充。您将能够使用e[i]作为计数器,计算a中代码为i的字符数。在c[i][0]中,c[i][1]…您可以在数组a中存储代码为i的字符的实际位置
第一步是迭代数组a,每次
将字符位置写入c[a[i][m]=i,其中m=e[a[i]]
增加e[a[i]]
您可以使用数组s存储符号的已打印位置数(s[j]是带有代码j的打印字符数)。第二步是迭代b,每次
输出c[b[i]][m],其中m=s[b[i]]
增加s[b[i]]
每个步骤消耗O(n)个时间,因此总时间复杂度为O(n)。需要注意的是,使用随机方法(如哈希表,您必须考虑命中概率)时,此复杂度不是mean。在最差的场景中,这种复杂性将是相同的。您只需将索引插入到由元素值键入的多重映射中,然后迭代另一个数组,找到您需要的第一个索引,然后将其从映射中删除。应为O(n log n):
std::multimap charmap;
for(无符号i=0;istd::cout second+1数组只包含a、b或c吗?我不明白你是如何给出答案的,因为a
和b
元素的值。你可以有一种int char\u map[256]={0};char\u map[symbol]“A/NaveBoBar”数组包含AZ(只有小写)的任何组合,没有数字/特殊字符/空格。@ dasHealth- C++中的索引从0开始,而不是1。为什么你的输出不反映这一点,至少不会混淆事物?你是说复杂性= O(n)?如果A&B是双链接列表而不是数组?不是。我说的是哈希表插入是O(1)。要将数组A中的N个条目添加到哈希表中,它将是O(N)。我们在每个索引处维护一个列表。我刚才提到列表是双l
int c[256][n]; // O(n) memory
int s[256]; // O(1) memory
int e[256]; // O(1) memory
std::multimap<char, int> charmap;
for (unsigned i = 0; i < sizeof a; i++) {
charmap.emplace(a[i], i);
}
for (char c : b) {
auto it = charmap.find(c);
std::cout << it->second + 1 << " ";
charmap.erase(it);
}