从右侧到奇数位置,从左侧到就位
move from right side to odd positions and from left side to even in-place
本文关键字:位置 更新时间:2023-10-16
给定了一系列非空数。您必须将所有项目从右侧移动到奇数位置(零基于零),从左侧将所有项目移动到左侧 - 甚至位置,如下所示:
原始数据:0 2 4 6 8 10 12 14 1 3 5 7 9 11 13
结果:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
o(n)时间复杂性有哪些原位算法?它的实现是什么?
在这里解决了逆问题(该算法基本上可以倒置,但看起来很丑)。
这只是算法本身。有关详细信息,解释和替代方法,请参见反问题的答案。
- 初始化指向右侧元素的指针到N/2。
- 获得最大的子阵列,其尺寸为3 k 1
- join(3 k 1)/2个元素,来自数组的开头,(3 k 1)/2元素元素的元素交换适当的子阵列。更新泳池指针。
- 从位置1、3、9,... 3 k-1 :将元素移至其在子阵列中的适当位置(从右侧到位置的左侧的元素,从右侧到奇数位置),替换的元素也应移至其适当位置等。直到此过程返回起始位置为止。
- 使用步骤2 ..4。 ,递归处理阵列的其余部分
这个问题比OP中提到的反面问题要简单,因为在这里我们必须从较大的阵列开始,以与执行周期领导者算法相同的顺序(反问题必须单独这样做,并且以相反的顺序从较小的开始到获得O(n)复杂性)。
我终于找到了直接和反向问题的解决方案:
#include <iterator>
#include <algorithm>
#include <type_traits>
#include <limits>
#include <deque>
#include <utility>
#include <cassert>
template< typename Iterator >
struct perfect_shuffle_permutation
{
static_assert(std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::random_access_iterator_tag >::value,
"!");
using difference_type = typename std::iterator_traits< Iterator >::difference_type;
using value_type = typename std::iterator_traits< Iterator >::value_type;
perfect_shuffle_permutation()
{
for (difference_type power3_ = 1; power3_ < std::numeric_limits< difference_type >::max() / 3; power3_ *= 3) {
powers3_.emplace_back(power3_ + 1);
}
powers3_.emplace_back(std::numeric_limits< difference_type >::max());
}
void
forward(Iterator _begin, Iterator _end) const
{
return forward(_begin, std::distance(_begin, _end));
}
void
backward(Iterator _begin, Iterator _end) const
{
return backward(_begin, std::distance(_begin, _end));
}
void
forward(Iterator _begin, difference_type const _size) const
{
assert(0 < _size);
assert(_size % 2 == 0);
difference_type const left_size_ = *(std::upper_bound(powers3_.cbegin(), powers3_.cend(), _size) - 1);
cycle_leader_forward(_begin, left_size_);
difference_type const rest_ = _size - left_size_;
if (rest_ != 0) {
Iterator middle_ = _begin + left_size_;
forward(middle_, rest_);
std::rotate(_begin + left_size_ / 2, middle_, middle_ + rest_ / 2);
}
}
void
backward(Iterator _begin, difference_type const _size) const
{
assert(0 < _size);
assert(_size % 2 == 0);
difference_type const left_size_ = *(std::upper_bound(powers3_.cbegin(), powers3_.cend(), _size) - 1);
std::rotate(_begin + left_size_ / 2, _begin + _size / 2, _begin + (_size + left_size_) / 2);
cycle_leader_backward(_begin, left_size_);
difference_type const rest_ = _size - left_size_;
if (rest_ != 0) {
Iterator middle_ = _begin + left_size_;
backward(middle_, rest_);
}
}
private :
void
cycle_leader_forward(Iterator _begin, difference_type const _size) const
{
for (difference_type leader_ = 1; leader_ != _size - 1; leader_ *= 3) {
permutation_forward permutation_(leader_, _size);
Iterator current_ = _begin + leader_;
value_type first_ = std::move(*current_);
while (++permutation_) {
assert(permutation_ < _size);
Iterator next_ = _begin + permutation_;
*current_ = std::move(*next_);
current_ = next_;
}
*current_ = std::move(first_);
}
}
void
cycle_leader_backward(Iterator _begin, difference_type const _size) const
{
for (difference_type leader_ = 1; leader_ != _size - 1; leader_ *= 3) {
permutation_backward permutation_(leader_, _size);
Iterator current_ = _begin + leader_;
value_type first_ = std::move(*current_);
while (++permutation_) {
assert(permutation_ < _size);
Iterator next_ = _begin + permutation_;
*current_ = std::move(*next_);
current_ = next_;
}
*current_ = std::move(first_);
}
}
struct permutation_forward
{
permutation_forward(difference_type const _leader, difference_type const _size)
: leader_(_leader)
, current_(_leader)
, half_size_(_size / 2)
{ ; }
bool
operator ++ ()
{
if (current_ < half_size_) {
current_ += current_;
} else {
current_ = 1 + (current_ - half_size_) * 2;
}
return (current_ != leader_);
}
operator difference_type () const
{
return current_;
}
private :
difference_type const leader_;
difference_type current_;
difference_type const half_size_;
};
struct permutation_backward
{
permutation_backward(difference_type const _leader, difference_type const _size)
: leader_(_leader)
, current_(_leader)
, half_size_(_size / 2)
{ ; }
bool
operator ++ ()
{
if ((current_ % 2) == 0) {
current_ /= 2;
} else {
current_ = (current_ - 1) / 2 + half_size_;
}
return (current_ != leader_);
}
operator difference_type () const
{
return current_;
}
private :
difference_type const leader_;
difference_type current_;
difference_type const half_size_;
};
std::deque< difference_type > powers3_;
};
相关文章:
- 将值指定给向量(2D)的向量中的某个位置
- 使用Unreal C++获取VR耳机的世界位置/方向
- 写入位置0x0000000C时发生访问冲突
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 如何使用cudaMallocManaged在指针位置初始化对象?(C++)
- 无法获取webot::PositionSensor对象中位置传感器的值
- 非常量变量只读位置的赋值
- 如何定义更改car类中car位置的方法
- 使用迭代器时如何访问对象在向量中的位置?
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 求最大元素位置的分治算法
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 为什么我的点没有在 OpenGL 中绘制鼠标所在的位置?
- 如何将元素添加到向量的字符串位置
- 如何选择在 csv 文件中输出的位置
- 无法打开 fstream C++文件,即使它与 .cpp 位于同一位置
- 如何在特定位置追加 json 文件
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- OpenGL - 在 NDC 中计算位置适用于着色器,但不适用于'regular'程序