先甩链接https://www.hackerrank.com/challenges/larrys-array
首先想到的一个思路是:从数列中找最小值并确定最小值的位置
1. 如果最小值的位置在数列的第一位,则在1..n中继续找次小值所在的位置(可以理解为移除首位的最小值,然后在剩余数列中寻找最小值);
2. 如果最小值的位置在数列的第二位,则选取0..3三个数组成子数列进行一次轮转将最小值移至首位
3. 如果最小值的位置在数列的第二位之后,则选取最小值之前的两个数与最小值一起组成子数列进行两次轮转将最小值移至子数列的第一位,然后继续循环进行操作
4. 当剩余数列的长度不足3时,退出循环,并核对结果数列是否是升序排序,是输出YES,否输出NO
题目的输入条件:
第一行:测试案例的数量
第二行:数列的数字个数
第三行:数列的各个数字,使用一个空格进行分隔
实现代码如下:
1 # 轮转3个数的列表 0<-1, 1<-2, 2<-0 2 def rotate(p_arr_sub): 3 arr_sub_r = p_arr_sub 4 temp = arr_sub_r[0] 5 arr_sub_r[0] = arr_sub_r[1] 6 arr_sub_r[1] = arr_sub_r[2] 7 arr_sub_r[2] = temp 8 return arr_sub_r 9 10 t = int(input().strip()) 11 12 for a0 in range(t): 13 n = int(input().strip()) 14 arr = [int(arr_temp) for arr_temp in input().strip().split(‘ ‘)] 15 16 # 列表的起点序号 17 begin_index = 0 18 19 while begin_index < n - 2: 20 # 获取最小值在列表中的位置序号 21 min_value_index = arr.index(min(arr[begin_index:])) 22 # 最小值位置序号与列表起点相同, 则说明无需进行轮转 23 # 列表起点位置后移一位 24 if min_value_index == begin_index: 25 begin_index += 1 26 # 最小值位置在起点序号之后一位, 则需要进行一次轮转 27 elif min_value_index == begin_index + 1: 28 arr_sub = rotate(arr[begin_index:begin_index+3]) 29 arr[begin_index:begin_index + 3] = arr_sub 30 # 最小值位置在起点序号之后两位以上, 则获取最小值之前的两位与最小值一起构成一个长度为3的子列表进行两次轮转 31 else: 32 arr_sub = rotate(rotate(arr[min_value_index-2:min_value_index+1])) 33 arr[min_value_index-2:min_value_index+1] = arr_sub 34 35 if sorted(arr) == arr: 36 print("YES") 37 else: 38 print("NO")
获得结果如下:
一共20个测试案例前10个都正常通过,后10个全部超时,拿到最后一个案例的输入与期望输出在本地进行测试后发现结果是正确的,所以剩下的事情就是如何进行效率的优化。
重新分析了一下题目,输出要求是YES or NO,所以并不一定需要进行实际的轮转操作,参照https://en.wikipedia.org/wiki/Parity_of_a_permutation的思路最终的解决代码如下:
1 t = int(input().strip()) 2 3 for a0 in range(t): 4 n = int(input().strip()) 5 arr = [int(arr_temp) for arr_temp in input().strip().split(‘ ‘)] 6 7 inversions = 0 8 for i in range(n-1): 9 for j in range(i+1, n): 10 if arr[i] > arr[j]: 11 inversions += 1 12 13 if inversions % 2 == 0: 14 print("YES") 15 else: 16 print("NO")
Larry's Array 解题思路及过程
时间: 2024-10-11 08:08:27