如何在 O(1) 时间内将数组归零?

2024-04-07

有没有一种方法可以将数组归零,时间复杂度为 O(1)?很明显,这可以通过for-loop、memset来完成。但它们的时间复杂度不是O(1)。


Yes

但不是任何数组。它需要一个专门为此工作而设计的数组。

template <typename T, size_t N>
class Array {
public:
    Array(): generation(0) {}

    void clear() {
        // FIXME: deal with overflow
        ++generation;
    }

    T get(std::size_t i) const {
        if (i >= N) { throw std::runtime_error("out of range"); }

        TimedT const& t = data[i];
        return t.second == generation ? t.first : T{};
    }

    void set(std::size_t i, T t) {
        if (i >= N) { throw std::runtime_error("out of range"); }

        data[i] = std::make_pair(t, generation);
    }


private:
    typedef std::pair<T, unsigned> TimedT;

    TimedT data[N];
    unsigned generation;
};

原理很简单:

  • 我们使用以下方法定义一个纪元generation属性
  • 当设置一个项目时,会记录该项目被设置的纪元
  • 只能看到当前纪元的项目
  • 因此,清除相当于增加纪元计数器

该方法有两个问题:

  • 存储增加:对于每个项目,我们存储一个纪元
  • 生成计数器溢出:有一个最大纪元数

后者可以使用真正的大整数来阻止(uint64_t以更多存储为代价)。

前者是自然的结果,一种可能的解决方案是使用存储桶来淡化该问题,例如将最多 64 个项目与单个计数器关联,并使用一个位掩码来标识哪些项目在该计数器内有效。


EDIT:只是想回到桶的想法。

原来的解决方案有一个每个元素 8 字节(64 位)的开销(如果已经 8 字节对齐)。根据存储的元素,这可能是也可能不是一个大问题。

如果是大事,想法是使用桶;当然,就像所有的权衡一样,它会进一步减慢访问速度。

template <typename T>
class BucketArray {
public:
     BucketArray(): generation(0), mask(0) {}
     
     T get(std::size_t index, std::size_t gen) const {
         assert(index < 64);

         return gen == generation and (mask & (1 << index)) ?
                data[index] : T{};
     }

     void set(std::size_t index, T t, std::size_t gen) {
         assert(index < 64);

         if (generation < gen) { mask = 0; generation = gen; }

         mask |= (1 << index);
         data[index] = t;
     }

private:
     std::uint64_t generation;
     std::uint64_t mask;
     T data[64];
};

请注意,这个包含固定数量元素的小数组(我们实际上可以对其进行模板化并静态检查它是否小于或等于 64)仅具有 16 字节的开销。这意味着我们有一个每个元素 2 位的开销.

template <typename T, size_t N>
class Array {
    typedef BucketArray<T> Bucket;
public:
    Array(): generation(0) {}
    
    void clear() { ++generation; }

    T get(std::size_t i) const {
        if (i >= N) { throw ... }

        Bucket const& bucket = data[i / 64];
        return bucket.get(i % 64, generation);
    }

    void set(std::size_t i, T t) {
        if (i >= N) { throw ... }

        Bucket& bucket = data[i / 64];
        bucket.set(i % 64, t, generation);
    }

private:
    std::uint64_t generation;
    Bucket data[N / 64 + 1];
};

我们将空间开销降低了... 32。现在数组甚至可以用来存储char例如,而在此之前,这将是令人望而却步的。代价是访问速度变慢,因为我们进行了划分and取模(什么时候我们会得到一种标准化的操作,一次返回两个结果?)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 O(1) 时间内将数组归零? 的相关文章

随机推荐

  • 从计算机商店删除证书

    我很难让 powershell 删除意外安装到我们所有 Windows 7 计算机上的计算机商店的证书 作为示例 我提供了证书安装位置的屏幕截图 这不是实际的证书 我们有几百台机器 因此我们希望尽可能自动化地完成此操作 如果有人可以提供一种
  • 请识别此算法:数据流中的概率前 k 个元素

    我记得几年前听说过以下算法 但在网上找不到任何参考 它仅使用 m 个计数器来识别 n 个元素的数据流中的前 k 个元素 或重量级元素 这对于在使用最少内存的情况下查找热门搜索词 网络滥用者等特别有用 算法 对于每个元素 如果该元素还没有计数
  • 加速“最接近”字符串匹配算法

    我目前正在处理一个非常大的位置数据库 并尝试将它们与现实世界的坐标相匹配 为了实现这一点 我下载了地名数据集 https www geonames org export 其中包含很多条目 它给出了可能的名称和纬度 经度坐标 为了尝试加快该过
  • Java 相当于一个类。 == 与 .equals 相同

    我们可以做一个 on a Class变量而不是equals并期望相同的结果 例如 Class clazz xyz Case A if clazz Date class do something Case B if Date class eq
  • jqGrid 传递值到表单编辑

    我有一个 jqGrid 字段 如下所示 colModel name Enabled index Enabled width 45 editable true edittype checkbox editoptions value 1 0 f
  • 安装 laravel --prefer-dist

    我正在他们的网站上关注 Laravel 安装 我遇到了这条线 composer create project laravel laravel prefer dist 现在 到底是什么 prefer dist部分意思是 我在他们的文档中看不到
  • 使用 SpannedgridLayoutManager 后,recyclerView 占用了顶部的大量空间

    我想在 recyclerview 的 Spanned GridLayoutManager 中显示列表数据 但是添加辅助类 Spanned GridLayoutmanager 后 在我的 recycleview 中占用了顶部的大量空间 iam
  • 防止@EnableWebMvc注释的类被@ComponentScan拾取

    我有以下测试类 ActiveProfiles DataTC test RunWith SpringJUnit4ClassRunner class ContextConfiguration classes BaseTestConfigurat
  • MyBatis:使用动态查询比较字符串值

    我正在使用 MyBatis 来映射一些需要比较的查询String争论 myString 我的地图绘制者界面 is public Map
  • NHibernate二级缓存性能问题

    我正在使用 NHibernate 使用每个请求会话模式开发一个 MVC 应用程序 大多数时候用户只是读取数据 因此我尝试通过以下方式使用 NHibernate 的二级缓存 我设置了 SysCache 并使所有持久实体可缓存 缓存使用 non
  • 普通数组也是动态的吗? [复制]

    这个问题在这里已经有答案了 以下是我的C代码 main int a 1 a 0 10 a 1 12 printf d n a 1 copy arr a printf d a 1 以下是输出 12 12 它不应该给出数组越界或类似的东西吗 或
  • 使用 setText 方法时 JLabel 不更新

    在我目前正在进行的项目中 我希望通过 Jlabel 显示几条信息 GUI 中的其他位置有一些按钮和文本字段 允许更改所述信息 我想更新 JLabel 但文本永远不会更改 或在启动时更新 我尝试使用并发来更新标签 正如本网站上其他问题中所建议
  • Expression.Lambda() 的参数问题

    更新 这确实有效 我很愚蠢 我有以下扩展方法 public static string ExtMethod this object self object myparameter 在运行时 可以通过多种方式调用它 我认为这些都是可能的 Ex
  • 按 dplyr 中 mutate_at 中的名称排除列

    我正在尝试做一些非常简单的事情 但无法找出正确的指定方法 我只是想从中排除一些命名列mutate at 如果我指定位置 它就可以正常工作 但我不想对位置进行硬编码 例如 我想要与此相同的输出 mtcars gt mutate at c 1
  • 如何将textmate文件资源管理器移到右侧?

    如何将textmate文件资源管理器移到右侧 Update 对于更高版本的 textmate 请参阅这个答案 https stackoverflow com a 53817213 908886 对于 Textmate 2 在回答此问题后很久
  • 为什么我们不在 http 上发送二进制而不是文本?

    看起来二进制会更紧凑并且可以以标准方式反序列化 为什么使用文本代替 这似乎效率低下 Web 框架被迫只做与字符串相关的事情 为什么没有二进制标准 网络将变得更快 浏览器将能够非常快速地加载二进制页面 如果我要启动一个二进制协议 HBP 超二
  • 如何在iOS中创建非圆角UIProgressView

    我将 UIProgressView 子类化为 import UIKit class MyProgressView UIProgressView override func sizeThatFits size CGSize gt CGSize
  • 与证书颁发机构签署证书请求

    我想使用 TLS 相互身份验证来对 go 中制作的 API 上的客户端进行身份验证 我已经创建了一个证书颁发机构 假设鲍勃有一个他想要与客户端一起使用的密钥对 Bob 创建了一个证书请求并希望我验证他的证书以获得授权并 在 API 上进行身
  • 导航控制器的后退按钮问题 (iPhone)

    所以这是我正在寻找的功能 1 主菜单没有导航栏2 主菜单中的所有其他屏幕都是如此 3 它应该正确地设置动画 我部分地让它工作 只是不是后退按钮部分 在主菜单 viewDidLoad 中 我只需执行以下操作 self navigationCo
  • 如何在 O(1) 时间内将数组归零?

    有没有一种方法可以将数组归零 时间复杂度为 O 1 很明显 这可以通过for loop memset来完成 但它们的时间复杂度不是O 1 Yes 但不是任何数组 它需要一个专门为此工作而设计的数组 template