我是靠谱客的博主 英勇镜子,最近开发中收集的这篇文章主要介绍LeetCode 189 旋转数组,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

补数据结构的作业的时候,被老师要求写出时间复杂度为O(n),空间复杂度为O(1),的算法。断断续续想了一天,终于有了一个大概思路,写出来自己跑了几组数据,没发现什么问题。在LeetCode上找到了这道题提交了一下,用时战胜了89%的提交者(最优的那种算法真的是简单又高效,但是我实在是没有想出来,就不在这里剽窃了)。下面叙述一下我的想法。

首先明确,k>=n时,应有k%=n,因为移动一圈跟不动是没区别的。

大概的思路是从a元素出发,把它放到它在结果中应该到的位置(设为b)中去,并保存b位置原来的值。然后从b位置出发,重复该操作,又回到a位置(eg. a->b->c->e->a)之后,如果数组中的元素还没有移动完毕,应该移动到a+1,然后继续循环移动 。

那么问题是如何确定是否已经将数组中的元素全部移动完毕和是否已经绕了一圈呢?

经过思考,我们会发现经过多少个圈才能移动完成和每圈需要移动的元素数是可以根据n和k算出来的。

1. 确定每圈可以移动的元素数

当我们从a出发又回到a时,走过的长度是n和k的最小公倍数,而 最小公倍数=(n*k)/gcd(n,k),同时,每移动k步就意味着一个元素的移动,因此 每圈移动的元素数为 n/(gcd(n,k))

2.圈数

n/(n/(gcd(n,k)))=gcd(n,k)

代码如下

void rotate(vector<int>& nums, int k) {
        int n=nums.size();
        k%=n;
        if(k)
        {
            int gnk=gcd(n,k),temp,next,cur;
            for(int i=0;i<gnk;i++)
            {
                cur=i;
                temp=nums[i];
                for(int j=0;j<n/gnk;j++)
                {
                    next=(cur+k)%n;//循环移动
                    swap(temp,nums[next]);
                    cur=next;
                }
            }
        }
    }
    int gcd(int a,int b)//在这里用欧几里得算法计算最大公约数
    {
        int t;
        while(b)
        {
            t=a;
            a=b;
            b=t%a;
        }
        return a;
    }
    void swap(int& a,int& b)//三变量法元素交换
    {
        int t;
        t=a;
        a=b;
        b=t;
    }

 

强烈推荐去了leetcode上看看其他解法,比我这个强多了

 

最后

以上就是英勇镜子为你收集整理的LeetCode 189 旋转数组的全部内容,希望文章能够帮你解决LeetCode 189 旋转数组所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部