数组循环移位
来源:互联网 发布:金山软件拆分 编辑:程序博客网 时间:2024/05/17 01:32
数组循环移位
要求:设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂段为O(N),且只允许使用两个附加变量。
分析:
在翻阅《编程之美》时看到了这道题,虽然书上已经给了一个完善简便的解法,但是自己却想到了一个时间O(n)空间O(1)的算法。这里先给出书中的算法,再给出我的算法。
书中使用的是三次逆序操作。
比如要对“abcd1234”右移4位,可以:
(1)逆序abcd:“abcd1234” -> “dcba1234”
(2)逆序1234:“dcba1234” -> “dcba4321”
(3)全部逆序:“dcba4321” -> “1234abcd”
代码:
def reverse(arr, left, right): i = left while i <= ((left + right) / 2): arr[left], arr[right] = arr[right], arr[left] i += 1 left += 1 right -= 1def rightShift(arr, n, k): k %= n reverse(arr, 0, n-k-1) reverse(arr, n-k, n-1) reverse(arr, 0, n-1)
另一种思路:
先循环移动k%l次,从每一轮循环仅仅移动i,i+k,i+2k等位置,使其在本轮循环结束后除初始移动的元素外,其余元素均处于最终位置。
比如对”1 2 3 4 5 6 7 8“右移动三位:
第一轮:”1 2 3 4 5 6 7 8“ -> "4 2 3 7 5 6 1 8"
第二轮:"4 2 3 7 5 6 1 8" -> "4 5 3 7 8 6 1 2"
第三轮:"4 5 3 7 8 6 1 2" -> "4 5 6 7 8 3 1 2"
最后,再将末尾的”3 1 2“进行排序。得到”4 5 6 7 8 1 2 3“。
我没能正确的实现上述算法,而且,最后的排序也使得时间复杂度大于O(n)。最后在网上搜寻,找到了这种方法的延伸版本。
延伸版本的思路是每一轮循环移动除自己本身的所有元素到最终位置。
比如对”1 2 3 4 5 6 7 8“右移动两位:
第一轮:”1 2 3 4 5 6 7 8“ -> "3 2 3 4 5 6 7 8" -> "3 2 5 4 5 6 7 8" -> "3 2 5 4 7 6 7 8" (给末尾的位置赋予初始值)-> "3 2 5 4 7 6 1 8"
第二轮:"3 2 5 4 7 6 1 8" -> "3 4 5 4 7 6 1 8" -> "3 4 5 6 7 6 1 8" -> "3 4 5 6 7 8 1 8" (交换)-> "3 4 5 6 7 8 1 2"
代码:
def leftShift3(arr, k): arr_l = len(arr) i = 0 while i < gcd(arr_l, k): j = i tmp = arr[j] while True: arr[j] = arr[(j + k) % arr_l] j = (j + k) % arr_l if j == i: break print i, ' '.join(arr) arr[(j + arr_l - k) % arr_l] = tmp print ' '.join(arr) i += 1
总结:
第二种思路虽然满足题目要求,但是实现起来比第一种思路复杂很多。如果实际中会用,还是用第一种思路的解法。
- 数组循环移位算法
- 数组循环移位问题
- 数组循环移位
- 数组循环移位
- 数组循环移位
- 数组循环移位(转)
- 数组循环移位
- 数组循环移位
- 数组循环移位
- 数组循环移位
- 2.17数组循环移位
- 数组循环移位问题
- 数组循环移位
- 数组循环移位
- 2.17 数组循环移位
- 字符数组循环移位
- 数组循环移位
- 数组循环移位
- vector的标准用法linux
- 对Docker的价值和应用场景分析
- 利用pod trunk发布程序
- Tyvj 题目1023 奶牛的锻炼(DP)
- 增量会话对象——DeltaSession
- 数组循环移位
- RSA密钥之C#格式与Java格式转换
- New world,Good luck!
- 颠覆式前端UI开发框架:React
- Git客户端(Windows系统)的使用 本地仓库使用
- C语言sprintf使用出现段错误
- Delphi相关的几个博客
- uva 230
- mysql数据库索引的创建及使用