尋找峰值[中等]

在這里插入圖片描述

優質博文IT-BLOG-CN

一、題目

峰值元素是指其值嚴格大于左右相鄰值的元素。給你一個整數數組nums,找到峰值元素并返回其索引。數組可能包含多個峰值,在這種情況下,返回 任何一個峰值 所在位置即可。

你可以假設nums[-1] = nums[n] = -∞

你必須實現時間復雜度為O(log n)的算法來解決此問題。

示例 1:
輸入:nums = [1,2,3,1]
輸出:2
解釋:3是峰值元素,你的函數應該返回其索引2

示例 2:
輸入:nums = [1,2,1,3,5,6,4]
輸出:15
解釋:你的函數可以返回索引1,其峰值元素為2;或者返回索引5, 其峰值元素為6

提示:
1 <= nums.length <= 1000
-231 <= nums[i] <= 231 - 1
對于所有有效的i都有nums[i] != nums[i + 1]

二、代碼

方案一:尋找最大值

由于題目保證了nums[i]≠nums[i+1],那么數組nums中最大值兩側的元素一定嚴格小于最大值本身。因此,最大值所在的位置就是一個可行的峰值位置。

我們對數組nums進行一次遍歷,找到最大值對應的位置即可。

class Solution {public int findPeakElement(int[] nums) {int idx = 0;for (int i = 1; i < nums.length; ++i) {if (nums[i] > nums[idx]) {idx = i;}}return idx;}
}

時間復雜度: O(n),其中n是數組nums的長度。
空間復雜度: O(1)

方案二:二分查找

首先要注意題目條件,在題目描述中出現了nums[-1] = nums[n] = -∞,這就代表著 只要數組中存在一個元素比相鄰元素大,那么沿著它一定可以找到一個峰值。

根據上述結論,我們就可以使用二分查找找到峰值

查找時,左指針l,右指針r,以其保持左右順序為循環條件

根據左右指針計算中間位置m,并比較mm+1的值,如果m較大,則左側存在峰值,r = m,如果m + 1較大,則右側存在峰值,l = m + 1

class Solution {public int findPeakElement(int[] nums) {int left = 0, right = nums.length - 1;for (; left < right; ) {int mid = left + (right - left) / 2;if (nums[mid] > nums[mid + 1]) {right = mid;} else {left = mid + 1;}}return left;}
}

時間復雜度: O(log?n),其中n是數組nums的長度。
空間復雜度: O(1)

方案三:迭代爬坡

俗話說「人往高處走,水往低處流」。如果我們從一個位置開始,不斷地向高處走,那么最終一定可以到達一個峰值位置。

因此,我們首先在[0,n)的范圍內隨機一個初始位置i,隨后根據nums[i?1],nums[i],nums[i+1]三者的關系決定向哪個方向走:
【1】如果nums[i?1]<nums[i]>nums[i+1],那么位置i就是峰值位置,我們可以直接返回i作為答案;
【2】如果nums[i?1]<nums[i]<nums[i+1],那么位置i處于上坡,我們需要往右走,即i←i+1

如果nums[i?1]>nums[i]>nums[i+1],那么位置i處于下坡,我們需要往左走,即i←i?1

如果nums[i?1]>nums[i]<nums[i+1],那么位置i位于山谷,兩側都是上坡,我們可以朝任意方向走。

如果我們規定對于最后一種情況往右走,那么當位置i不是峰值位置時:
【1】如果nums[i]<nums[i+1],那么我們往右走;
【2】如果nums[i]>nums[i+1],那么我們往左走。

class Solution {public int findPeakElement(int[] nums) {int n = nums.length;int idx = (int) (Math.random() * n);while (!(compare(nums, idx - 1, idx) < 0 && compare(nums, idx, idx + 1) > 0)) {if (compare(nums, idx, idx + 1) < 0) {idx += 1;} else {idx -= 1;}}return idx;}// 輔助函數,輸入下標 i,返回一個二元組 (0/1, nums[i])// 方便處理 nums[-1] 以及 nums[n] 的邊界情況public int[] get(int[] nums, int idx) {if (idx == -1 || idx == nums.length) {return new int[]{0, 0};}return new int[]{1, nums[idx]};}public int compare(int[] nums, int idx1, int idx2) {int[] num1 = get(nums, idx1);int[] num2 = get(nums, idx2);if (num1[0] != num2[0]) {return num1[0] > num2[0] ? 1 : -1;}if (num1[1] == num2[1]) {return 0;}return num1[1] > num2[1] ? 1 : -1;}
}

時間復雜度: O(n),其中n是數組nums的長度。在最壞情況下,數組nums單調遞增,并且我們隨機到位置0,這樣就需要向右走到數組nums的最后一個位置。
空間復雜度: O(1)

方法四:二分查找優化

我們可以發現,如果nums[i]<nums[i+1],并且我們從位置i向右走到了位置i+1,那么位置i左側的所有位置是不可能在后續的迭代中走到的。

這是因為我們每次向左或向右移動一個位置,要想「折返」到位置i以及其左側的位置,我們首先需要在位置i+1向左走到位置i,但這是不可能的。

并且根據方法二,我們知道位置i+1以及其右側的位置中一定有一個峰值,因此我們可以設計出如下的一個算法:
【1】對于當前可行的下標范圍[l,r],我們隨機一個下標i
【2】如果下標i是峰值,我們返回i作為答案;
【3】如果nums[i]<nums[i+1],那么我們拋棄[l,i]的范圍,在剩余[i+1,r]的范圍內繼續隨機選取下標;
【4】如果nums[i]>nums[i+1],那么我們拋棄[i,r]的范圍,在剩余[l,i?1]的范圍內繼續隨機選取下標。

在上述算法中,如果我們固定選取i[l,r]的中點,那么每次可行的下標范圍會減少一半,成為一個類似二分查找的方法,時間復雜度為 O(log?n)

class Solution {public int findPeakElement(int[] nums) {int n = nums.length;int left = 0, right = n - 1, ans = -1;while (left <= right) {int mid = (left + right) / 2;if (compare(nums, mid - 1, mid) < 0 && compare(nums, mid, mid + 1) > 0) {ans = mid;break;}if (compare(nums, mid, mid + 1) < 0) {left = mid + 1;} else {right = mid - 1;}}return ans;}// 輔助函數,輸入下標 i,返回一個二元組 (0/1, nums[i])// 方便處理 nums[-1] 以及 nums[n] 的邊界情況public int[] get(int[] nums, int idx) {if (idx == -1 || idx == nums.length) {return new int[]{0, 0};}return new int[]{1, nums[idx]};}public int compare(int[] nums, int idx1, int idx2) {int[] num1 = get(nums, idx1);int[] num2 = get(nums, idx2);if (num1[0] != num2[0]) {return num1[0] > num2[0] ? 1 : -1;}if (num1[1] == num2[1]) {return 0;}return num1[1] > num2[1] ? 1 : -1;}
}

時間復雜度: O(log?n),其中n是數組nums的長度。
空間復雜度: O(1)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/715674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715674.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python統計分析——泊松回歸

參考資料&#xff1a;用python動手學統計學 概率分布為泊松分布、聯系函數為對數函數的廣義線性模型叫作泊松回歸。解釋變量可以有多個&#xff0c;連續型和分類型的解釋變量也可以同時存在。 1、案例說明 分析不同氣溫與啤酒銷量的關系。構造不同氣溫下的銷量的數學模型&…

Java之美[從菜鳥到高手演變]之Json類型數據的處理

JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。 易于人閱讀和編寫。同時也易于機器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一個子集。 JSON采用完全獨立于語言的文本格式&#xff0c;但是也使…

Unity--自動版面(Horizontal Layout Croup)||Unity--自動版面(Vertical Layout Group)

Unity--自動版面&#xff08;Horizontal Layout Croup&#xff09; Horizontal Layout Croup&#xff1a; “水平布局組”組件將其子布局元素并排放置。它們的寬度由各自的最小&#xff0c;首選和靈活的寬度決定&#xff0c;具體取決于以下模型&#xff1a; 所有子布局元素的…

el-form里面表單遍歷渲染,里面放el-row,一行放3個表單怎么實現

需求&#xff1a; 需要實現 el-form里面的表單遍歷渲染&#xff0c;里面放el-row,一行放3個表單怎么實現&#xff1f; 廢話不多說直接上demo <el-form ref"form" :model"form" label-width"80px"><el-row v-for"(row, index) in M…

服務器硬件基礎知識全解析

在信息技術日新月異的今天&#xff0c;服務器作為數據處理和存儲的核心&#xff0c;其重要性不言而喻。了解服務器硬件基礎知識&#xff0c;對于IT從業者以及廣大技術愛好者來說&#xff0c;都是不可或缺的技能。本文將詳細解析服務器硬件的基礎知識&#xff0c;幫助讀者建立起…

BUGKU bp

打開環境&#xff0c;他提示了弱密碼top1000&#xff0c;隨便輸入密碼123抓包爆破 發現長度都一樣&#xff0c;看一下響應發現一段js代碼&#xff0c;若r值為{code: bugku10000}&#xff0c;則會返回錯誤&#xff0c;通過這一句“window.location.href success.php?coder.cod…

計算機二級Python刷題筆記------基本操作題11、14、17、21、30(考察列表)

文章目錄 第十一題&#xff08;列表遍歷&#xff09;第十四題&#xff08;len&#xff09;第十七題&#xff08;len、insert&#xff09;第二十一題&#xff08;append&#xff09;第三十題&#xff08;二維列表&#xff09; 第十一題&#xff08;列表遍歷&#xff09; 題目&a…

mysql數據庫root權限讀寫文件

如果沒有shell&#xff0c;只有數據庫權限的情況下&#xff1a; 1. udf 提權提示沒有目錄&#xff1a;使用數據流創建目錄 1. select xxx into outfile C:\\phpstudy_pro\\Extensions\\MySQL5.5.29\\lib\::$INDEX_ALLOCATION;2. select xxx into outfile C:\\phpstudy_pro\…

springcloud和基礎服務的搭建以及封裝

代碼倉庫地址&#xff1a;https://github.com/zhaoyiwen-wuxian/springcloud-common page分頁也進行了封裝&#xff0c;只需要添加到pom中&#xff0c;將會自動進行分頁&#xff0c;并且后端不需要寫任何的分頁數據。只需要前端自己傳分頁參數即可&#xff0c;并且里面封裝了很…

Hololens 2應用開發系列(2)——MRTK基礎知識及配置文件配置(上)

Hololens 2應用開發系列&#xff08;2&#xff09;——MRTK基礎知識及配置文件配置 一、前言二、MRTK基礎知識2.1 MRTK概述2.2 MRTK運行邏輯2.3 MRTK配置文件介紹2.4 MRTK服務 三、配置文件使用3.1 總配置文件3.2 相機配置3.3 其他配置 參考文獻 一、前言 在前面的文章中&…

高效運維監測:全面掌控IT基礎設施與應用性能

在現代IT環境中&#xff0c;確保服務器、網絡設備和應用程序的穩定運行至關重要。為了實現這一目標&#xff0c;運維團隊需要一套高效、靈活的監測系統&#xff0c;能夠實時追蹤各種性能指標&#xff0c;并在出現問題時迅速發出警報。本文將詳細介紹這樣一套監測系統&#xff0…

WebServer -- 數據庫連接池

目錄 &#x1f382;基礎知識 &#x1f6a9;整體內容 &#x1f33c;單例模式創建 &#x1f382;連接池&#xff08;代碼實現&#xff09; 初始化 獲取 && 釋放連接 銷毀連接池 &#x1f351;RAII 機制釋放數據庫連接 定義 實現 &#x1f382;基礎知識 什么是…

使用 Docker 部署 Answer 問答平臺

1&#xff09;介紹 GitHub&#xff1a;https://github.com/apache/incubator-answer Answer 問答社區是在線平臺&#xff0c;讓用戶提出問題并獲得回答。用戶可以發布問題并得到其他用戶的詳細答案、建議或信息。回答可以投票或評分&#xff0c;有助于確定有用的內容。標簽和分…

Ps:歷史記錄面板

Ps菜單&#xff1a;窗口/歷史記錄 Window/History 歷史記錄 History面板提供了對圖像編輯過程中所進行更改的深入控制&#xff0c;可以讓用戶回溯并查看每一步操作&#xff0c;從而允許用戶輕松撤銷錯誤或比較不同的編輯效果。 ◆ ◆ ◆ 常用操作方法與技巧 “歷史記錄”面板…

CentOS7設置虛擬機語言為中文

1.查看本地安裝的語言 locale -a 是一個Linux命令&#xff0c;用于列出系統中可用的所有區域設置&#xff08;locales&#xff09;它包含了各種語言和地區的不同設置。 打開終端&#xff08;右鍵open terminal&#xff09;輸入 locale -a 查看本地安裝的語言&#xff1a; 其中z…

如何在Unity項目中使用Plastic SCM進行版本控制

引言 Plastic SCM是一個版本控制系統&#xff0c;專為處理大型項目而設計&#xff0c;特別適用于游戲開發中的Unity項目。它提供了強大的分支和合并工具&#xff0c;使團隊能夠高效地協作開發。 安裝和設置 安裝Plastic SCM 訪問Plastic SCM官網下載客戶端。根據您的操作系…

一些可以訪問gpt的方式

1、Coze扣子是新一代 AI 大模型智能體開發平臺。整合了插件、長短期記憶、工作流、卡片等豐富能力&#xff0c;扣子能幫你低門檻、快速搭建個性化或具備商業價值的智能體&#xff0c;并發布到豆包、飛書等各個平臺。https://www.coze.cn/ 2、https://poe.com/ 3、插件阿里…

EasyRecovery16電腦硬盤數據恢復軟件功能詳解

在數字化時代&#xff0c;人們在日常生活和工作中越來越依賴于電腦和移動設備。不管是個人用戶還是企業&#xff0c;數據的重要性都不言而喻。然而&#xff0c;數據丟失和損壞的風險也隨之增加&#xff0c;因此&#xff0c;數據恢復軟件的需求也日益增長。 EasyRecovery 16是一…

不同材質的油封及其使用溫度限制

油封&#xff0c;也稱為旋轉軸密封件&#xff0c;是防止潤滑油從機器和軸承內部間隙泄漏的重要部件。油封的有效性很大程度上取決于其承受運行過程中所暴露溫度的能力。 材料問題&#xff1a;不同材料及其溫度限制 制造油封所使用的不同材料可以承受不同的溫度范圍。這里有一…

【打工日常】使用docker部署在線Photopea用于linux下替代ps

一、Photopea介紹 linux沒有ps適配&#xff0c;對于有時候工作來說確實不方便&#xff0c;我找了很久&#xff0c;才找到了一款功能可以跟ps接近的在線軟件&#xff0c;使用docker部署就可以了。它是ps的最佳替代品之一&#xff0c;其界面幾乎與ps相同&#xff0c;只不過它是在…