PTA平台 自测-3 数组元素循环右移问题

该博客介绍了中国大学MOOC的数据结构课程中的自测题目——数组元素循环右移问题。文章分析了如何在不使用额外数组的情况下,以最少的移动次数完成循环右移,并通过两个案例探讨了不同情况下的移动策略,最终给出了Python 3的代码实现并已通过所有测试案例。
摘要由CSDN通过智能技术生成

中国大学MOOC-陈越、何钦铭-数据结构-起步能力自测题

自测-3 数组元素循环右移问题   (20分)

一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M≥0)个位置,即将A中的数据由(A0 A1.. A{N-1})变换为(A{N-M} ... A{N-1} A0 A1 ... A{N-M-1} )(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:

每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(M≥0);第2行输入N个整数,之间用空格分隔。

输出格式:

在一行中输出循环右移MM位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

问题分析:

要实现移动次数尽量少,所以我们可以思考一下最少需要移动几次。最少应该是N次(M不为0时)。如果我们假设N个整数中存在一个没有移动,那么这个元素之前的第M个元素需要移动到这个位置,那么这个元素如果没有移动,它的值将被覆盖,换句话说这个数组将永远失去一个元素,显然这种情况是不被允许的。所以每个元素都需要至少移动一次。

Case 1 我们首先观察一个例子,数组(1, 2, 3, 4, 5, 6, 7)向右移动2个位置,那么1需要到3,3需要到5,5需要到7,7需要到2,2需要到4,4需要到6,6需要到1,如此移动7次,我们实现了循环移动的过程,而且仅仅移动了7次。是不是所有的数组都可以通过这样的方式实现移动呢?答案是不一定。

Case 2 我们再来观察一个例子数组(1, 2, 3, 4, 5, 6)向右移动2个位置,那么1需要到3,3需要到5,5需要到1。那么接下来呢?我们如果不选择作出一些改变的话,我们将进入这个1,3,5的循环里,而这显然不是我们需要的,所以再回到1之后,我们需要调整到2,然后开始新的循环移动,这样就可以完成2,4,6的位置改变。

这时候需要思考,究竟什么情况下Case 1会发生,而什么时候case 2会发生呢?

假设我们最最开始移动的元素下标为a0,数组长度为L,移动距离为M (讨论中M<L, 因为M=L时数组发生没有任何改变,而M>L总可以划归到M<L的情况里) ,已经发生了第k次移动,那么很容易得到第k次移动时,需要被移动的元素的下标为:

ak = (a0 + M* k) % L. 而如果ak等于a0,那么case 2就会发生,如果ak始终不等于a0,那么我们一直处于case 1中。

更具体一点:

case 1:(M* k) % L != 0

case 2 :(M* k) % L  == 0

在完成了以上分析后,我们得到代码实现如下:(python 3, 已通过PTA平台全部测试案例)

 

 

 
  1. # This code is designed to adjust given array/list
  2. # by shifting every element by M units rightwards
  3. # circularly
  4. # e.g. a= [1, 2, 3, 4, 5, 6] M=2 -->
  5. # this input set will give out [5, 6, 1, 2, 3, 4]
  6. # sample input :
  7. # 6 2 (length of array, shift distance)
  8. # 1 2 3 4 5 6 (elements of array)
  9. ############## input processing #################
  10. InputInfo_1 = input("")
  11. InputInfo_2 = input("")
  12. InputList_1 = InputInfo_1.split(' ', 1)
  13. array_len = int( InputList_1[0] ) #get the length of array
  14. shift_dist = int ( InputList_1[1] ) #shift distance rightwards
  15. InputList_2 = InputInfo_2.split(' ', array_len-1 )
  16.  
  17. originalArray = [0] * array_len #initiate a list with all 0s
  18. for k in range(array_len) :
  19. originalArray[k] = int( InputList_2[k] ) # Transfer string var to int var
  20.  
  21. shift_dist = shift_dist % array_len
  22.  
  23. pre_repository = originalArray[0]
  24. this_index = ( 0 + shift_dist ) % array_len
  25. for m in range(array_len) :
  26. if (shift_dist * (m+1) ) % array_len != 0 :
  27. post_repository = originalArray[this_index]
  28. else:
  29. post_repository = originalArray[ (this_index +1 ) % array_len]
  30. originalArray[this_index] = pre_repository
  31. if (shift_dist * (m+1) ) % array_len != 0 :
  32. pre_repository = post_repository
  33. this_index = ( this_index + shift_dist ) % array_len
  34. else:
  35. pre_repository = originalArray[ (this_index +1 ) % array_len]
  36. this_index = ( this_index + shift_dist + 1 ) % array_len
  37.  
  38. for n in range(array_len - 1):
  39. print(originalArray[n], end =' ')
  40. print(originalArray[-1])
  41.  

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值