公司标签。Google, Microsoft, Facebook, Apple, Amazon, Bloomberg, Uber, Quora, Walmart Labs
据全球各地的程序员报道,在包括谷歌在内的一些巨型组织中,这是一个经常被问到的问题。如果这个问题也出现在你的面试中呢?你能以最佳方式解决这个问题吗?
问题说明
给定一个整数阵列nums ,找到一个峰值元素,并返回其索引。如果数组包含多个峰值,则返回任何一个峰值的索引。
- 峰值元素是指严格大于其相邻元素的一个元素。
注意:你可以想象nums[-1] = nums[n] = -∞。
挑战。你 能写出一个能在**O(log n)**时间内运行的算法吗?
准则。
1 <= nums.length <= 1000-231 <= nums[i] <= 231 - 1nums[i] != nums[i + 1]为所有有效的i
例子
让我们来看看一些例子,以提高我们对这个问题的理解。
| 例1: 输入:nums = [1, 2, 3, 1 ]输出。2 解释。3是一个峰值元素,你的函数应该返回索引数2. 例2: 输入:nums = [1, 2, 1, 3, 5, 6, 4] 输出。1或5解释 。你的函数可以返回索引号1或2,其中峰值元素分别为2和6。 例3: 输入:nums = [10, 12, 14, 16, 18] 输出。4 解释。18是一个峰值元素,你的函数应该返回索引号4. 例4: 输入:nums = [20, 15, 10, 5] 输出。0 解释:20是一个峰值元素,你的函数应该返回索引号0. 例子5: 输入:nums = [5, 5, 5] 输出。0、1或2 解释。你的函数可以返回任何索引,因为所有的元素都是一样的,因此每个元素都是一个峰值元素。 |
方法1:使用线性搜索
**方法。**最简单的方法是在数组中使用线性搜索来寻找峰值元素。你必须遍历数组中的每一个元素,检查它是否大于其相邻的元素。如果是,则返回它。在解决这个问题时,有几个基础是你必须考虑的。
- 如果数组只包含一个元素,那么它将是峰值元素。
- 如果数组中的数字按升序排列(例3), 峰值元素将是最后一个。
- 如果数组中的数字按降序排列(例4),则峰值元素将是第一个元素。
- 如果数组中所有的元素都是一样的(例5), 每个元素都是一个峰值元素.
解决方法**:** 现在,让我们看看解决这个问题的代码。
def peak_element(nums):
n = len(nums)
if n == 1:
return 0
if nums[0] >= nums[1]:
return 0
if nums[n - 1] >= nums[n - 2]:
return n - 1
for i in range(1, n - 1):
if nums[i] >= nums[i - 1] and nums[i] >= nums[i + 1]:
return i
让我们在我们的例子上运行这段代码。
| # 例一 nums = [1, 2, 3, 1 ]print(peak_element(nums)) # 2 # 例 2nums = [1, 2, 1, 3, 5, 6, 4] print(peak_element(nums)) # 1 # 例 3nums = [10, 12, 14, 16,18] print(peak_element(nums)) # 4 # 示例 4nums = [20, 15, 10, 5] print(peak_element(nums)) # 0 # 示例 5nums = [5, 5, 5] print(peak_element(nums )) # 0 |
好哇!它通过了所有的测试案例。
复杂度分析。
- 时间复杂度:在最坏的情况下,这个方法会遍历整个数组。因此,这个方法的时间复杂度将是O(n)。
- 空间复杂度。这个方法的空间复杂度是常数,即O(1)。
讨论。总是有改进的余地。你能以比O(n)更好的复杂度找到峰值元素吗?
方法2:使用二进制搜索 [最佳解决方案]
**方法。**在这种方法中,你必须将数组的中间元素与它的相邻元素进行比较。当右边的邻居大于中间元素时,你将在右边找到峰值元素,当左边的邻居大于中间元素时,你将在左边找到峰值元素。在较大的邻接元素上递归应用同样的方法,直到找到峰值元素。
算法。
- 初始化左边为
0,右边为len(nums)-1。 - 重复以下步骤,直到左数小于右数或找到峰值元素为止。
- 将中间元素初始化为左+右/ 2,并检查中间元素是否是峰值元素。如果是,则返回它。
- 如果
nums[mid-1] > nums[mid],则将右元素设为right = mid – 1 - 如果
nums[mid+1] > nums[mid],则将左元素设为left = mid + 1
下图通过一个例子说明了上述算法的工作原理,比如给定的数组是[1,2,1,3,5,6,4]
解决方案。 现在,让我们看一下代码。
def peak_element(nums) :
n = len(nums)
left = 0
right = n - 1
while left <= right:
mid = (left + right) // 2
if (mid == 0 or nums[mid-1] <= nums[mid]) and (mid == n-1 or nums[mid] >= nums[mid+1]):
return mid
if mid == 0 or nums[mid-1] > nums[mid]:
right = mid - 1
else:
left = mid + 1
测试案例分析。 让我们在我们的例子上运行这段代码。
| # 例子1 nums = [1, 2, 3, 1 ]print(peak_element(nums)) # 2 # 示例 2nums = [1, 2, 1, 3, 5, 6, 4] print(peak_element(nums)) # 5 # 示例 3nums = [10, 12, 14, 16,18] print(peak_element(nums)) # 4 # 示例 4nums = [20, 15, 10, 5] print(peak_element(nums)) # 0 # 示例 5nums = [5, 5, 5] print(peak_element(nums )) # 1 |
是的!它通过了所有的测试案例。
复杂度分析。
- 时间复杂度:在这个方法中,我们使用二进制搜索来寻找峰值元素。因此,时间复杂性将是O(logn)。
- 空间复杂度。这个方法的空间复杂度保持不变,即O(1)。
结语
我希望你喜欢这个编码面试问题。请继续**关注并订阅更多**有趣的编码问题。
文章来源:ShubhamSayon和Rashi Agarwal
- Fiverr和Upwork上最抢手的技能之一是网络刮痧。不要搞错了。_以编程方式从网站中提取数据_是当今世界上由网络和远程工作塑造的关键生活技能。
- 那么,你想掌握使用Python的BeautifulSoup进行网络搜刮的艺术吗?
- 如果答案是肯定的--本课程将带领你从网络刮削的初学者变成专家。
现在就**加入BeautifulSoup的网络刮削大师班**,明天就可以掌握它了!
The post[Google Interview] How To Find the Peak Element In Python?first appeared onFinxter.