循环移位算法


循环移位法

参考文章:内容连接。文章主要从数组,字符串,链表三种情况下,介绍循环移位的具体实现。这里只梳理一下文章脉络。

数组循环移位

方法一:取模法

这个方法在 Leetcode 189 中已经用过了,作者这里考虑了两种新情况:

  • 如果移位位数 K 是数组长度 len(s) 的倍数的话,那么就不用移位了;
  • 如果 K 是负数,就是往相反方向(向左移)

方法二:时间换空间

如果要解决上面的问题,那我们便一次一次的考虑,总共移动 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,难度中等。这里便不再展开了。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM