我很难用Divide&Conquer算法编写代码。最大的问题是我不知道如何处理偶数个元素的子集。
一个典型的问题是“给出一个输入数组nums,其中nums [i]≠nums [i + 1],找到一个峰值元素并返回其索引”。
书上的算法说:
如果nums [n / 2]
否则,如果nums [n / 2]
其他n / 2位是峰值
当n = 2时,我不知道如何处理n / 2。因为该算法似乎总是将集合分为2部分。当子集包含奇数个元素(例如[a,b,c])时,很容易理解。我可以找到中间元素b并进行比较。当子集仅包含两个元素时,说[a,b]。我找不到要比较的中间元素。
为使递归正常终止,我在python代码中添加了一些逻辑。我一次也做不到。我想知道是否可以考虑问题中与[a,b]之类的子集有关的终止条件?
class Solution:
def findPeakElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
def finder(start, end):
if start == end:
return start
if end - start == 1:
return end if nums[start] < nums[end] else start
N = end-start+1
if(nums[start+N//2]<nums[start+N//2-1]):
return finder(start,start+N//2-1)
elif(nums[start+N//2]<nums[start+N//2+1]):
return finder(start+N//2+1,end)
else:
return start+N//2
return finder(0,len(nums)-1)
答案 0 :(得分:0)
我建议简化您的逻辑和样式,以便更轻松地推断代码。您正在反复计算N//2
,这浪费了周期,而且嘈杂且在语义上毫无意义。在函数开始时将工作保存在名为mid
的变量中,以赋予其含义。在代码中增加间距以减少视觉噪音,并使其愉快(并且可能)逐步执行。
对于start
,end
和N
,这是一个必须考虑和操作的额外变量-start
和end
足以处理所有情况,并且混淆这些变量在您的代码中似乎是一个问题。
由于您已经知道算法,因此您已接近解决方案。不过,数组的奇偶性不是问题,唯一的问题是mid == 0
和mid == len(nums) - 1
的边缘情况。在这两种情况下,只有一个邻居,因此如果我们分别尝试nums[mid-1]
和nums[mid+1]
,我们将崩溃。解决这些问题只是在尝试进行这些比较之前测试mid
是否不在数组的一端或另一端。
将它们放在一起,该函数中需要发生的所有事情是:
def finder(start, end):
mid = (start + end) // 2
if mid > 0 and nums[mid] < nums[mid-1]:
return finder(start, mid - 1)
elif mid < end and nums[mid] < nums[mid+1]:
return finder(mid + 1, end)
else:
return mid