您现在的位置是:主页 > news > 青岛网站建设市场分析/做网店自己怎么去推广
青岛网站建设市场分析/做网店自己怎么去推广
admin2025/5/13 9:10:39【news】
简介青岛网站建设市场分析,做网店自己怎么去推广,南京网站制作链接,企业公共信息服务平台文章目录环转替代法数组翻转法这几天可被一道题愁死了,我废寝忘食但怎么都做不出来,好不容易想出来了一种方法吧,结果超时了,又想出一种办法吧,结果哦答案还对不上,给我气得,记录一下这坑爹题我…
青岛网站建设市场分析,做网店自己怎么去推广,南京网站制作链接,企业公共信息服务平台文章目录环转替代法数组翻转法这几天可被一道题愁死了,我废寝忘食但怎么都做不出来,好不容易想出来了一种方法吧,结果超时了,又想出一种办法吧,结果哦答案还对不上,给我气得,记录一下这坑爹题我…
这几天可被一道题愁死了,我废寝忘食但怎么都做不出来,好不容易想出来了一种方法吧,结果超时了,又想出一种办法吧,结果哦答案还对不上,给我气得,记录一下这坑爹题
文章目录
- 环转替代法
- 数组翻转法
这几天可被一道题愁死了,我废寝忘食但怎么都做不出来,好不容易想出来了一种方法吧,结果超时了,又想出一种办法吧,结果哦答案还对不上,给我气得,记录一下这坑爹题

- 我的超时方法,理解起来非常简单,就是一次只往右挪一位,循环k次就好
- 我还想了一个方法和答案第二种环转方法类似,但是咋都不对,下面重点讲一下这个,这个方法比较难,答案还用到了高代里的一些结论,但是作为数学组选手,俺就喜欢挑战这种方法
环转替代法
- 好家伙,那答案写的,我看了俩小时都没懂,结果看到一个圆圈,突然就理解了
- 这道题的解题关键就是得知道遍历次数,啥叫遍历次数呢?简单来说就是圈圈个数,这里的圈必须首尾一致,比如下面这个例子,圈圈个数是2(1351和2462)
- 答案里得到遍历次数的公式太牛啦太牛啦,这不看答案怎么知道啊?
- 关键公式an=bkan=bkan=bk
- aaa是圈数,即完成一次遍历要绕数组几圈。nnn是整个数组的长度,bbb是每次遍历的元素个数,比如上个例子里的b=3b=3b=3,kkk就是往右行走的步数(题目给的)
- 这个公式咋来的呢,力扣的官方解释一开始我没看懂,但结合圆圈来理解就非常清晰了
- 这里a=1,n=6,k=2,b=3
- 再来个例子
- 这里a = 2,n=3,k=2,b=3
- 所以an=bkan=bkan=bk的解释就是遍历一次走过的距离
- ananan是根据转圈数得到,因为首尾一致,肯定是圈,每个圈又有n个元素
- bkbkbk是根据遍历的元素×迈开步子的长度
- 以上证明了an=bkan=bkan=bk成立的合法性,接着要求bbb的大小了,因为只要求得b的大小,就能求遍历次数=nb=\frac{n}{b}=bn,这个公式应该好理解,只要认同每个遍历都包含相同的元素个数即可
- 现在已知得到是n,kn,kn,k,怎样能不通过aaa来求bbb呢?高级的知识点来了:ananan肯定是nnn的倍数毋庸置疑,ananan也是kkk的倍数这也毋庸置疑,然后肯定要aaa取最小,是可以无限转圈,但俺们要求用最小的圈数回到原点,所以可以得到an=lcm(n,k)an=lcm(n,k)an=lcm(n,k),即ananan是n,kn,kn,k的最小公倍数
- 因此就有b=ank=lcm(n,k)kb=\frac{an}{k}=\frac{lcm(n,k)}{k}b=kan=klcm(n,k)
- 于是数组一共要遍历的次数为nb=nklcm(n,k)=gcd(n,k)\frac{n}{b}=\frac{nk}{lcm(n,k)}=gcd(n,k)bn=lcm(n,k)nk=gcd(n,k)
- gcdgcdgcd是最大公约数
- 解释一下这个式子,为什么nknknk除以最大公倍数就等于最小公约数了呢,高代里有证明啊,可以去看,直观可以这么理解
- (nk/nk的最大公约数gcd)保证了这个数被拆解成质数的乘积里,肯定没有重复的数,这不就是最大公倍数嘛!
- 然后在每个遍历里,每个位置的元素都有自己想要去的地方,同时每个位置又都被其他位置的元素惦记
- 所以指定一个temp/prev,表示某个位置要出去的那个值,比如0位置的元素要出去找下家了,temp=nums[0]=1,那哪位下家能取这个值呢,是x=(0+k)modnx=(0+k)\mod\ nx=(0+k)mod n呐,于是nums[x]=tempnums[x] = tempnums[x]=temp
- 然后就是要得到遍历停止的条件了,这里的遍历停止指的是一个圈结束哈,标记开始的位置startstartstart,记录现在的位置currentcurrentcurrent,当current=startcurrent=startcurrent=start时,一次遍历结束
- 直接看代码吧
class Solution:def rotate(self, nums: List[int], k: int) -> None:n = len(nums)count = gcd(n,k)start = 0 for start in range(0,count):#这里容易出错,没有取余运算的话可能会出现current>n-1的情况current = (start+k)%nprev = nums[start]while current!=start:#python里的swap就是这么简单粗暴nums[current], prev = prev,nums[current] #这一步是最妙的,一个式子实现完美转圈圈,我竟然还分了两种情况0~k-1和k~n-1current = (current+k) % nnums[start] = prev
数组翻转法
- 最简单,没有什么深度理解的地方,就是翻转3次
- 关于翻转的代码可以看一下,指定两个指针,start和end,从左右往中间夹击
C++代码
class Solution {
public:void reverse(vector<int>& nums, int start, int end) {while (start < end) {swap(nums[start], nums[end]);start += 1;end -= 1;}}void rotate(vector<int>& nums, int k) {k %= nums.size();reverse(nums, 0, nums.size() - 1);reverse(nums, 0, k - 1);reverse(nums, k, nums.size() - 1);}
};