zoukankan      html  css  js  c++  java
  • LeetCode #189 Rotate Array 数组 双变量 双指针

    Description


    Given an array, rotate the array to the right by k steps, where k is non-negative.

    Example 1:

    Input: [1,2,3,4,5,6,7] and k = 3
    Output: [5,6,7,1,2,3,4]
    Explanation:
    rotate 1 steps to the right: [7,1,2,3,4,5,6]
    rotate 2 steps to the right: [6,7,1,2,3,4,5]
    rotate 3 steps to the right: [5,6,7,1,2,3,4]
    

    Example 2:

    Input: [-1,-100,3,99] and k = 2
    Output: [3,99,-1,-100]
    Explanation: 
    rotate 1 steps to the right: [99,-1,-100,3]
    rotate 2 steps to the right: [3,99,-1,-100]
    

    Note:

    • Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
    • Could you do it in-place with O(1) extra space?



    思路


    解法一

    拷贝一份源数组,以便在覆盖 nums 里的元素之后能够检索到该位置的旧值是什么,从而在下次更新 nums 时使用该旧值。

    算法只需要 nums.size() 次更新操作,所以时间复杂度为 O(n);拷贝了一份数组,空间复杂度 O(n)

    耗时16ms, ranking 80%

    class Solution {
    public:
        void rotate(vector<int>& nums, int k) {
            if (nums.empty()) return;
    
            k = k % nums.size();
            if (!k) return;
    
            vector<int> backup = nums;
            for (int i = 0; i < nums.size(); ++i) {
                int next_idx = abs(i + k) % (nums.size());
                nums[next_idx] = backup[i];
            }
        }
    };
    



    解法二

    如果只观察间隔为 k 的元素的更新操作,比如 [1 2 3 4 5], k = 2 的话,只看 [1 3 5] 这三个位置的更新操作,那么在每次更新操作中,真正被用到的数据只有上一次被覆盖元素的值与索引,比如更新 3 时,我们用到了值 1 和索引 0。因此可以利用双变量、双索引保存旧值与其位置,从而对解法一进行优化。

    额外需要注意的是,由于解法二是 pick 出了间隔为 k 的元素,那么就可能会漏掉另一部分的元素,比如上一段话中的 [2 4] 就被忽略了,因为 k = 2 时,指针永远在 [1 3 5] 这三个数据之间循环。因此,需要再加入一个保存起始位置的索引start_idx,当指针等于start_idx时, 说明当前更新操作陷入局部数据而死循环了,需要将start_idx与当前指针都自增,从而脱离死循环。

    算法最终会对数组的每个位置都执行一次更新操作,所以总共执行 nums.size() 次更新操作,时间复杂度为 O(n);用了五个临时变量保存算法必要的信息,空间复杂度 O(1)

    耗时16ms, ranking 80%

    class Solution {
    public:
        void rotate(vector<int>& nums, int k) {
            if (nums.empty()) return;
    
            k = k % nums.size();
            if (!k) return;
    
            int idx = 0;
            int start_idx = idx;  // mark starting point
            int prev = INT_MAX;
            int cur = nums[idx];
            int update_cnt = nums.size();  // only update size() times
            while (update_cnt > 0) {
                int next_idx = abs(idx + k) % (nums.size());
                prev = cur;
                cur = nums[next_idx];
                nums[next_idx] = prev;
                idx = next_idx;
    
                // avoid endless loop caused by even k
                if (idx == start_idx) {
                    ++start_idx;
                    idx = start_idx;
                    cur = nums[idx];
                }
    
                --update_cnt;
            }
        }
    };
    



    参考


  • 相关阅读:
    启动redis时报错:FATAL CONFIG FILE ERROR :Bad directive or wrong number of arguments
    转载Redis的三个框架:Jedis,Redisson,Lettuce
    转载Dubbo详解(一):Dubbo介绍和SpringBoot整合Dubbo+ZooKeeper
    Redisson如何实现类似incr的自增操作
    转载解决 com.alibaba.fastjson.JSONException: autoType is not support.
    转载springboot+mybatis实现数据库的读写分离
    转载dubbo服务被重复调用三次的原因
    js中实现函数防抖跟函数节流
    网站项目后台的目录命名为admin后,网页莫名其妙的变样了
    createreactapp不支持less的解决方式
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/12664207.html
Copyright © 2011-2022 走看看