我被分配了两个类似的任务,应该很容易,但我需要澄清我能用c ++做什么和不做什么。
任务1: 假设你有一个n个元素的数组,只包含两个不同的键,true和false。给出一个O(n)算法来重新排列列表,以便所有假元素都在真元素之前。您可以只使用恒定的额外空间。
对于任务2,我需要做同样的事情,但现在有一个额外的键“可能”。所以我需要对数组进行排序,以便在O(n)之前可能出现错误,并且可能先于true。
我决定在第一个任务上使用插入排序,在第二个任务上快速排序。我的第一个问题是,创建一个数组并使用true false和/或可能的值对它进行排序是否理想。在我看来,我想要改变false,true和0,1,2的所有值,并按数字升序排序数组。我会通过首先遍历数组并更改值然后排序后执行此操作。什么是改变价值观的最佳方式(如果需要的话)。这会使算法保持在O(n)时间吗?
感谢您的帮助!
答案 0 :(得分:8)
这是一种经典的排序算法,在O(n)时间内运行,称为counting sort。更准确地说,它在O(n + k)时间内运行并使用O(k)空间,其中k
是可能的键数。
在这里,您只有3个可能的键,true
maybe
和false
,所以k=3
。因为这是一个常量,所以它在big-O表示法中被消除,因此你得到O(n)运行时间和O(1)空间。
答案 1 :(得分:2)
1: 实施一种计数排序:只通过你的桌子计算' false'元素。然后将数量为false的元素写入数组,并使用true值填充数组的其余部分。
对于2:与1.相同,但这次计算既错又可能。然后像在1中一样填充数组。
答案 2 :(得分:2)
这个问题有点像家庭作业,但在现实世界中,std::partition
是适合这项工作的工具。
还有stable_partition
慢,但保留了排序,而partition_copy
是O(N)且稳定但通过复制占用了额外的空间。
对于第二项任务,只需拨打partition
两次,一次将false
与maybe
和true
分开,另一次将maybe
与{{}分开1}}。总费用仍为O(N)。
答案 3 :(得分:0)
循环遍历数组并计算真值的数量。这就是你需要做的。 false值的数量是array_size - #true。这与排序数组基本相同。
如果由于某种原因,你需要解压缩(例如,你需要一个位图用于绘图目的),只需将数组中的memset #false设置为false,并将数组的其余部分设置为true(反之亦然)。
答案 4 :(得分:0)
从一开始,找到第一个'true'元素。从那时起,找到第一个'false'元素。交换它们并重复其余元素,直到两个迭代器都相等。 O(n)表示有2个状态的数据。
对于3个州,我会做类似的但是使用额外的2个额外的迭代器来记住我从哪里'可能'。
我不确定它是否适用于4个项目。它可能大于O(n),因为有些项目可能会被夸大两次!