循环移位算法
Posted rongyupan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环移位算法相关的知识,希望对你有一定的参考价值。
循环移位法
参考文章:内容连接。主要从 数组,字符串,链表 三种情况下,介绍循环移位的具体实现。这里只梳理一下文章脉络。
数组循环移位
方法一:取模法
这个方法在 Leetcode 189 中已经用过了,作者这里考虑了两种新情况:
- 如果移位位数 K 是数组长度 len(s) 的倍数的话,那么就不用移位了;
- 如果 K 是负数,就是往相反方向(向左移)
取模法由于需要开辟一个新数组,长度为 len(s),这会增加算法的空间开销,并不符合空间为 O(1) 的原地算法。
方法二:时间换空间
如果要解决上面的问题,那我们便一次一次的考虑,总共移动 K 次。这样时间复杂度变成了 O(N*K),最大可达 O(N^2)。
方法三:空间换时间
就是将数组长度变成原来的两倍,拼在一起。这在 leetcode-189 也有相关的描述。
三次翻转法
所谓“翻转”,比如[0,N],就是把 0 和 N 交换位置,1和(N-1)交换位置……。算法描述:
- 先把[0, n - k - 1]翻转
- 然后把[n - k, n - 1]翻转
- 最后把[0, n - 1]翻转
这个算法其实很好证明。我们用箭头代表方向,初始数组为 A->B | C->D ;经过前两次反转后变成了 B<-A | D<-C ;最后整体翻转,C->D | A->B。翻转看箭头的方向就好了,这是自己想的比较直观的证明。实现翻转的代码描述为:
while (start < end) {
t = list[start];
list[start] = list[end];
list[end] = t;
start++;
end--;
}
字符串移位
这里给出的例题为检查是否包含的问题。直观解法是每移动一次就判断一次,那么需要判断 len(s) 次。
暴力法
就是上面最直观的方法。实现思路是:已知 S1 和 S2,每次都把 S1 左移一位,用指针 P1 和 P2 开始对两个字符串开始检查;每左移一次,两个指针就循环检查一次。
用空间换时间
拼接两个 S1 字符串,然后用两个指针开始对于新的 S1 和 S2 进行检查。
取模法
取模法实际上是对于空间换时间算法的取巧。我们假象 S1 后面还有一个 S1,实际上是用取模的方法实现的。
链表循环移位
源于 leetcode-61,难度中等。这里便不再展开了。
以上是关于循环移位算法的主要内容,如果未能解决你的问题,请参考以下文章