zoukankan      html  css  js  c++  java
  • 1920. 基于排列构建数组

    方法二:原地构建
    思路与算法

    我们也可以直接对原数组 \textit{nums}nums 进行修改。

    为了使得构建过程可以完整进行,我们需要让 \textit{nums}nums 中的每个元素 \textit{nums}[i]nums[i] 能够同时存储「当前值」(即 \textit{nums}[i]nums[i])和「最终值」(即 \textit{nums}[\textit{nums}[i]]nums[nums[i]])。

    我们注意到 \textit{nums}nums 中元素的取值范围为 [0, 999][0,999] 闭区间,这意味着 \textit{nums}nums 中的每个元素的「当前值」和「最终值」都在 [0, 999][0,999] 闭区间内。

    因此,我们可以使用类似「10001000 进制」的思路来表示每个元素的「当前值」和「最终值」。对于每个元素,我们用它除以 10001000 的商数表示它的「最终值」,而用余数表示它的「当前值」。

    那么,我们首先遍历 \textit{nums}nums,计算每个元素的「最终值」,并乘以 10001000 加在该元素上。随后,我们再次遍历数组,并将每个元素的值除以 10001000 保留其商数。此时 \textit{nums}nums 即为构建完成的数组,我们返回该数组作为答案。

    细节

    在计算 \textit{nums}[i]nums[i] 的「最终值」并修改该元素时,我们需要计算修改前 \textit{nums}[\textit{nums}[i]]nums[nums[i]] 的值,而 \textit{nums}nums 中下标为 \textit{nums}[i]nums[i] 的元素可能已被修改,因此我们需要将取下标得到的值对 10001000 取模得到「最终值」。

    代码

    C++Python3

    class Solution {
    public:
    vector<int> buildArray(vector<int>& nums) {
    int n = nums.size();
    // 第一次遍历编码最终值
    for (int i = 0; i < n; ++i){
    nums[i] += 1000 * (nums[nums[i]] % 1000);
    }
    // 第二次遍历修改为最终值
    for (int i = 0; i < n; ++i){
    nums[i] /= 1000;
    }
    return nums;
    }
    };
    复杂度分析

    时间复杂度:O(n)O(n),其中 nn 为 \textit{nums}nums 的长度。我们遍历了两次 \textit{nums}nums 数组并进行修改,每次遍历并修改的时间复杂度均为 O(n)O(n)。

    空间复杂度:O(1)O(1)

    作者:LeetCode-Solution
    链接:https://leetcode-cn.com/problems/build-array-from-permutation/solution/ji-yu-pai-lie-gou-jian-shu-zu-by-leetcod-gjcn/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    Robberies
    Big Event in HDU
    UVA 562 Dividing coins
    Little Rooks
    Bone Collector
    Piggy-Bank
    0-1背包问题之——饭卡
    Monkey and Banana
    The Triangle
    Burning Midnight Oil
  • 原文地址:https://www.cnblogs.com/qianxunslimg/p/15605770.html
Copyright © 2011-2022 走看看