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

来源:互联网 发布:spss编程抽样 编辑:程序博客网 时间:2024/06/07 12:35

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

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

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

输入格式:

每个输入包含一个测试用例,第1行输入N1N100)和M(M0);第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. originalArray = [0] * array_len #initiate a list with all 0s
  17. for k in range(array_len) :
  18. originalArray[k] = int( InputList_2[k] ) # Transfer string var to int var
  19. shift_dist = shift_dist % array_len
  20. pre_repository = originalArray[0]
  21. this_index = ( 0 + shift_dist ) % array_len
  22. for m in range(array_len) :
  23. if (shift_dist * (m+1) ) % array_len != 0 :
  24. post_repository = originalArray[this_index]
  25. else:
  26. post_repository = originalArray[ (this_index +1 ) % array_len]
  27. originalArray[this_index] = pre_repository
  28. if (shift_dist * (m+1) ) % array_len != 0 :
  29. pre_repository = post_repository
  30. this_index = ( this_index + shift_dist ) % array_len
  31. else:
  32. pre_repository = originalArray[ (this_index +1 ) % array_len]
  33. this_index = ( this_index + shift_dist + 1 ) % array_len
  34. for n in range(array_len - 1):
  35. print(originalArray[n], end =' ')
  36. print(originalArray[-1])

总结:

其实这题应该是在考察链表的数据结构,但是限于所学有限,尚不能实现,因而另辟蹊径选择了另外的实现手段。

等掌握了链表的构造方法之后,我会再更新这里的实现方法。




0 0