强推两位新生代歌手
一位是梁博,一位是蔡维泽
博哥自然不用多说
很多歌太好听了
蔡维泽是明日之子第二季的总冠军
台湾的歌手
可能大家不是很熟悉
大家可以听听他的一首歌
你终究不爱这世界
很有共鸣!
题目描述:
给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件:
① 如果这个数组是 [a1, a2, a3, ... , an] ,那么数组 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数;.
② 如果存在多种答案,你只需实现并返回其中任意一种.
示例 1:
输入: n = 3, k = 1
输出: [1, 2, 3]
解释: [1, 2, 3] 包含 3 个范围在 1-3 的不同整数, 并且 [1, 1] 中有且仅有 1 个不同整数 : 1
示例 2:
输入: n = 3, k = 2
输出: [1, 3, 2]
解释: [1, 3, 2] 包含 3 个范围在 1-3 的不同整数, 并且 [2, 1] 中有且仅有 2 个不同整数: 1 和 2
思路解析:
这道题我刚开始想的是回溯法,实在是太符合回溯的思想了,对回溯不熟悉的朋友可以看看我的这篇文章,里面有对回溯法的解析非常详细的步骤。看完之后在做这道题,应该是非常easy了。回到这题,采用回溯法解答,其实就没什么绕弯子的了。
代码如下:
class Solution(object):
def constructArray(self, n, k):
"""
回溯法
:type n: int
:type k: int
:rtype: List[int]
"""
all_array = []
def back(sub_arr=[], dis_arr=[]):
if len(sub_arr) == n and len(set(dis_arr)) == k:
all_array.append(sub_arr)
return True
if len(set(dis_arr)) > k and len(sub_arr) < n:
return
for i in range(1, n+1):
if i in sub_arr:
continue
if len(sub_arr) == 0:
back(sub_arr+[i])
else:
last_idx = sub_arr[-1]
new_dis = abs(last_idx-i)
flag = back(sub_arr + [i], dis_arr + [new_dis])
if flag is True:
return
back()
return all_array[0]
if __name__ == "__main__":
n, k = 3, 1
all_array = Solution().constructArray(n, k)
print(all_array)
然而放到本题超出时间限制了,应该是作者考察的就不是这一点吧。
但自己实在是不愿意再思考了,就看了些网上大佬的思路,只看一眼就看一眼,真TM牛逼,献上我的膝盖啊。就是找到了问题本身的规律,而且对一连串数的敏感度非常高。题目不是要我们找到两两之间数的不同差值的总数为k吗,而且这一连串数组中不能出现重复数字,那就好办了。我们依次将最左边(最小)的数和最右边(最大)的数做减法,这样能够控制不同差值的个数,因为差值肯定是递减的。牛逼吧!
代码如下:
class Solution(object):
def constructArray(self, n, k):
"""
翻转法,这个方法我只能说牛逼
:type n: int
:type k: int
:rtype: List[int]
"""
ans = list(range(1, n+1))
for i in range(k-1):
ans[i+1:] = reversed(ans[i+1:])
return ans
if __name__ == "__main__":
n, k = 3, 2
all_array = Solution().constructArray(n, k)
print(all_array)
但是执行效率不高,对此结果我严重表示怀疑但不提出上诉。