题目1:只使用一个用于交换数组元素的附加单元实现数组循环移动

一、题目

已知一个长度为n的数组和一个正整数k,并且最多只能使用一个用于交换数组元素的附加空间单元,设计算法得到原数组循环右移k次的结果。

二、分析

显然,如果每次都将一个数安排到它最后要到的那个地方,那么n个数只需要交换n-1次,就可以完成了。之所以是n-1次而不是n次,是因为如果n-1个数字都已经就位,那么最后一个数字肯定也就位了。

如果n与k互质,那么问题会简单很多,比如5个数:abcde,向右循环移动3个单位,最后的结果是cdeab,那么各轮变化的情况应该是这样的:

1)第0位和第3位换:dbcae((0+3)%5=3)

2)第0位和第1位换:bdcae((3+3)%5=1)

3)第0位和第4位换:edcab((1+3)%5=4)

4)第0位和第2位换:cdeab((4+3)%5=2)

可见,若每次都将变换后的第0位数字移动到它最终的位置上,移动的位数是用n模除一个首项为0、公差位k的等差数列各项的结果。

如果n并不与k互质,则需要先求出n与k的最大公因数x=gcd(n,k),将n分为x组,从第0位到第n-1位数字,依次分摊到各个组n0、n1、...、nx中,每个组有n/x个元素,因为n/x与k是互质的,所以也就可以套用上面的方法进行计算了。

实现循环左移的原理和思路与实现循环右移是一样的。

三、代码

#函数:打印数组
def printarr(arr):
    print(", ".join([str(c) for c in arr]))

#函数:求最大公约数
def gcd(a,b):
    temp = max(a, b) % min(a, b)
    if temp == 0:
        return min(a, b)
    else:
        return gcd(min(a, b), temp)

#函数:交换数组内两元素
def swapnum(arr, a, b):
    x = arr[a]
    arr[a] = arr[b]
    arr[b] = x

#1.输入n和k
input_n = input("请输入数组长度:")
input_k = input("请输入右移位数:")

n = int(input_n)
k = int(input_k)
x = gcd(n, k)

#2.初始化数组
arr = [i for i in range(1, n + 1)]
print("生成数组")
printarr(arr)

#3.移动数组
counter = 0
for i in range(int(len(arr) / x - 1)):
    for j in range(x):
        print("交换元素:" + str(j) + " ←→ " + str(((i + 1) * k + j) % len(arr)))
        swapnum(arr, j, ((i + 1) * k + j) % len(arr))
        printarr(arr)
        
#4.打印结果
print("交换最终结果")
printarr(arr)

四、运行结果

以下是该段代码在Python3.4.2中的运行结果:

232725_nBw9_1425762.png

END

转载于:https://my.oschina.net/Tsybius2014/blog/393382

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值