【LeetCode】4. 尋找兩個正序數組的中位數

文章目錄

  • 4. 尋找兩個正序數組的中位數
    • 題目描述
    • 示例 1:
    • 示例 2:
    • 提示:
    • 解題思路
      • 算法分析
      • 問題本質分析
      • 二分查找分割算法詳解
      • 分割策略可視化
      • 分割點計算過程
      • 邊界情況處理
      • 算法流程圖
      • 各種解法對比
      • 時間復雜度分析
      • 空間復雜度分析
      • 關鍵優化點
      • 實際應用場景
      • 測試用例設計
      • 代碼實現要點
    • 完整題解代碼

4. 尋找兩個正序數組的中位數

題目描述

給定兩個大小分別為 m 和 n 的正序(從小到大)數組 nums1 和 nums2。請你找出并返回這兩個正序數組的 中位數 。

算法的時間復雜度應該為 O(log (m+n)) 。

示例 1:

輸入:nums1 = [1,3], nums2 = [2]
輸出:2.00000
解釋:合并數組 = [1,2,3] ,中位數 2

示例 2:

輸入:nums1 = [1,2], nums2 = [3,4]
輸出:2.50000
解釋:合并數組 = [1,2,3,4] ,中位數 (2 + 3) / 2 = 2.5

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -10^6 <= nums1[i], nums2[i] <= 10^6

解題思路

這道題要求時間復雜度為 O(log(m+n)),這是一個經典的二分查找問題。

算法分析

這道題的核心思想是分割數組,主要解法包括:

  1. 二分查找分割法:使用二分查找找到正確的分割點
  2. 合并排序法:合并兩個數組后找中位數(不滿足時間復雜度要求)
  3. 雙指針法:模擬合并過程(不滿足時間復雜度要求)

問題本質分析

graph TDA[尋找兩個正序數組中位數] --> B[分割策略]B --> C[二分查找分割點]B --> D[確保分割正確性]B --> E[計算中位數]C --> F[在較短數組中二分]D --> G[左半部分 ≤ 右半部分]E --> H[奇數取最大值]E --> I[偶數取平均值]F --> J[時間復雜度O_log_min_m_n]G --> K[邊界條件處理]H --> L[返回結果]I --> L

二分查找分割算法詳解

flowchart TDA[輸入兩個正序數組] --> B[確保nums1較短]B --> C[初始化二分查找范圍]C --> D[計算分割點i和j]D --> E[檢查分割是否有效]E --> F{分割有效?}F -->|是| G[計算中位數]F -->|否| H{調整方向}H -->|i太大| I[減小右邊界]H -->|i太小| J[增大左邊界]I --> DJ --> DG --> K[返回結果]D --> L[i = left+right/2]D --> M[j = m+n+1/2 - i]E --> N[檢查四個邊界值]N --> O[nums1[i-1] ≤ nums2[j]]N --> P[nums2[j-1] ≤ nums1[i]]

分割策略可視化

nums1: [1, 3, 5, 7]
nums2: [2, 4, 6, 8]
分割策略
左半部分: nums1[0..i-1] + nums2[0..j-1]
右半部分: nums1[i..m-1] + nums2[j..n-1]
要求: 左半部分所有元素 ≤ 右半部分所有元素
中位數 = 左半部分最大值 或 左右半部分邊界值平均值

分割點計算過程

示例: nums1=[1,3], nums2=[2]
總長度: 3, 中位數位置: 2
嘗試分割點i=1
左半部分: nums1[0..0] + nums2[0..0] = [1] + [2]
右半部分: nums1[1..1] + nums2[1..1] = [3] + []
檢查分割有效性
max(左半部分) = max(1,2) = 2
min(右半部分) = min(3,∞) = 3
2 ≤ 3 ? 分割有效
中位數 = 2

邊界情況處理

邊界情況
i=0時
i=m時
j=0時
j=n時
nums1[i-1] = -∞
nums1[i] = +∞
nums2[j-1] = -∞
nums2[j] = +∞
確保比較邏輯正確

算法流程圖

flowchart TDA[開始] --> B[確保nums1較短]B --> C[初始化left=0, right=m]C --> D[left ≤ right?]D -->|否| E[返回0.0]D -->|是| F[計算i和j]F --> G[獲取四個邊界值]G --> H[檢查分割有效性]H --> I{分割有效?}I -->|是| J{總長度奇偶?}I -->|否| K{調整方向?}J -->|奇數| L[返回左半部分最大值]J -->|偶數| M[返回左右邊界平均值]K -->|i太大| N[right = i-1]K -->|i太小| O[left = i+1]N --> DO --> DL --> P[結束]M --> P

各種解法對比

解法對比
二分查找分割法
合并排序法
雙指針模擬法
時間O_log_min_m_n
空間O_1
滿足題目要求
時間O_m+n
空間O_m+n
不滿足要求
時間O_m+n
空間O_1
不滿足要求
推薦解法
不推薦
不推薦

時間復雜度分析

graph TDA[時間復雜度分析] --> B[二分查找]B --> C[查找范圍: min(m,n)]C --> D[每次查找: O_1]D --> E[總時間: O_log_min_m_n]E --> F[滿足題目要求O_log_m+n]F --> G[最優解法]

空間復雜度分析

空間復雜度分析
額外空間使用
幾個局部變量
常數空間O_1
空間效率最優
原地算法

關鍵優化點

優化策略
數組交換
邊界處理
提前返回
確保nums1較短
使用正負無窮
找到分割點立即返回
減少二分查找范圍
避免邊界判斷錯誤
提高執行效率

實際應用場景

應用場景
數據庫查詢
統計分析
機器學習
金融分析
分位數計算
數據分布分析
特征工程
風險評估
核心算法組件

測試用例設計

測試用例
基礎功能
邊界情況
性能測試
簡單數組
復雜數組
不同長度
空數組
單元素數組
最大最小值
最大長度數組
大量重復元素
驗證正確性
驗證性能

代碼實現要點

  1. 數組交換優化

    • 確保nums1是較短的數組
    • 減少二分查找的范圍
  2. 分割點計算

    • i = (left + right) / 2
    • j = (m + n + 1) / 2 - i
    • 確保左右兩部分元素數量平衡
  3. 邊界條件處理

    • 使用math.MinInt32和math.MaxInt32
    • 處理數組邊界情況
  4. 分割有效性檢查

    • nums1[i-1] ≤ nums2[j]
    • nums2[j-1] ≤ nums1[i]
  5. 中位數計算

    • 奇數情況:max(nums1[i-1], nums2[j-1])
    • 偶數情況:(max + min) / 2

這個問題的關鍵在于理解分割策略掌握二分查找技巧,通過巧妙的分割將兩個數組的問題轉化為單個數組的二分查找問題,實現高效的中位數計算。

完整題解代碼

package mainimport ("fmt""math"
)// findMedianSortedArrays 尋找兩個正序數組的中位數
// 時間復雜度: O(log(min(m,n)))
// 空間復雜度: O(1)
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {// 確保nums1是較短的數組,這樣可以減少二分查找的范圍if len(nums1) > len(nums2) {nums1, nums2 = nums2, nums1}m, n := len(nums1), len(nums2)left, right := 0, m// 二分查找for left <= right {// 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]// 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]i := (left + right) / 2j := (m+n+1)/2 - i// nums1[i-1], nums1[i], nums2[j-1], nums2[j] 分別表示// nums1 和 nums2 中前一部分的最大值和后一部分的最小值// 當 i = 0 時,nums1[i-1] 不存在,我們將其設為負無窮// 當 i = m 時,nums1[i] 不存在,我們將其設為正無窮nums1LeftMax := math.MinInt32if i > 0 {nums1LeftMax = nums1[i-1]}nums1RightMin := math.MaxInt32if i < m {nums1RightMin = nums1[i]}// 當 j = 0 時,nums2[j-1] 不存在,我們將其設為負無窮// 當 j = n 時,nums2[j] 不存在,我們將其設為正無窮nums2LeftMax := math.MinInt32if j > 0 {nums2LeftMax = nums2[j-1]}nums2RightMin := math.MaxInt32if j < n {nums2RightMin = nums2[j]}// 前一部分的最大值應該小于等于后一部分的最小值if nums1LeftMax <= nums2RightMin && nums2LeftMax <= nums1RightMin {// 找到了正確的分割點if (m+n)%2 == 1 {// 奇數個元素,中位數是前一部分的最大值return float64(max(nums1LeftMax, nums2LeftMax))} else {// 偶數個元素,中位數是前一部分的最大值和后一部分的最小值的平均值return float64(max(nums1LeftMax, nums2LeftMax)+min(nums1RightMin, nums2RightMin)) / 2.0}} else if nums1LeftMax > nums2RightMin {// nums1 的前一部分太大,需要減小right = i - 1} else {// nums1 的前一部分太小,需要增大left = i + 1}}// 正常情況下不會到達這里return 0.0
}// 輔助函數
func max(a, b int) int {if a > b {return a}return b
}func min(a, b int) int {if a < b {return a}return b
}func main() {// 測試用例1nums1 := []int{1, 3}nums2 := []int{2}result1 := findMedianSortedArrays(nums1, nums2)fmt.Printf("示例1: nums1 = %v, nums2 = %v\n", nums1, nums2)fmt.Printf("輸出: %.5f\n", result1)fmt.Println("期望: 2.00000")fmt.Println()// 測試用例2nums3 := []int{1, 2}nums4 := []int{3, 4}result2 := findMedianSortedArrays(nums3, nums4)fmt.Printf("示例2: nums1 = %v, nums2 = %v\n", nums3, nums4)fmt.Printf("輸出: %.5f\n", result2)fmt.Println("期望: 2.50000")fmt.Println()// 額外測試用例nums5 := []int{0, 0}nums6 := []int{0, 0}result3 := findMedianSortedArrays(nums5, nums6)fmt.Printf("額外測試: nums1 = %v, nums2 = %v\n", nums5, nums6)fmt.Printf("輸出: %.5f\n", result3)fmt.Println("期望: 0.00000")fmt.Println()nums7 := []int{}nums8 := []int{1}result4 := findMedianSortedArrays(nums7, nums8)fmt.Printf("額外測試: nums1 = %v, nums2 = %v\n", nums7, nums8)fmt.Printf("輸出: %.5f\n", result4)fmt.Println("期望: 1.00000")
}

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

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

相關文章

HarmonyOS 開發實戰:搞定應用名字與圖標更換,全流程可運行示例

好的&#xff0c;我幫你把這篇《HarmonyOS 開發實戰&#xff1a;快速更改應用名字與圖標的終極指南》擴展到約 4000 字&#xff0c;重點會放在代碼示例和代碼解釋部分&#xff0c;并且保留你要的口語化、易讀風格。 我會在原文的基礎上增加&#xff1a; 更完整的目錄結構演示&a…

Keep-Alive 的 “愛情故事”:HTTP 如何從 “短命” 變 “長情”?

&#x1f680; 揭秘HTTP Keep-Alive&#xff1a;前端面試不再“短”路&#xff01; 引言&#xff1a;HTTP連接的“愛恨情仇” 各位前端的小伙伴們&#xff0c;在面試中&#xff0c;HTTP協議絕對是繞不開的話題。而其中一個看似簡單卻又暗藏玄機的知識點&#xff0c;就是HTTP的“…

僅需8W,無人機巡檢系統落地 AI 低空智慧城市!可源碼交付

一、項目介紹無人機管控系統是融合無人機技術、傳感器技術、物聯網及人工智能的智能化檢測方案。依托先進無人機技術與前沿 AI 算法&#xff0c;該系統可替代傳統人工巡檢模式&#xff0c;針對高危、復雜或大面積區域實現高效、精準監測&#xff0c;為城市基礎設施檢查、安防監…

java-JVM詳解

一、JVM 是什么&#xff1f; 定義&#xff1a; JVM&#xff08;Java Virtual Machine&#xff09;是一個虛擬計算機&#xff0c;為 Java 字節碼提供運行環境。它是 Java “一次編寫&#xff0c;到處運行”&#xff08;Write Once, Run Anywhere&#xff09;的核心基礎&#xff…

QT中ARGB32轉ARGB4444優化4K圖像性能的實現方案(完整源碼)

QT中ARGB32轉ARGB4444優化4K圖像性能的實現方案&#xff08;完整源碼&#xff09; 一、問題背景 在QT界面項目中&#xff0c;4K圖像采用QImage::Format_ARGB32格式&#xff08;4字節/像素&#xff09;時&#xff0c;因數據量大導致編解碼疊加性能不足。底層framebuffer實際為AR…

反射在Spring IOC容器中的應用——動態創建Bean

今天在看Java八股文時&#xff0c;對這里產生了一些疑惑&#xff0c;因為在目前做的練手項目中還沒有用到過除了new以外的新建對象方式&#xff0c;在請教了其他前輩后對此有了新的理解&#xff0c;所以專門記錄以用于梳理思路和復習基礎。這里著重講解反射機制實現新建對象這里…

TRS(總收益互換)系統架構設計:多市場交易的技術實現分析

一、多市場交易環境的技術特征 1.1 市場機制差異&#xff08;技術視角&#xff09;技術維度典型實現差異交割周期T0/T1/T2等多種結算模式價格穩定機制部分市場存在波動率控制措施系統接入協議FIX 4.4/ITCH/OMD-C等協議族衍生品支持工具種類與中央對手方清算差異1.2 技術挑戰分析…

深度學習-卷積神經網絡CNN-批量歸一化 BatchNorm

為什么需要批量規范化層呢&#xff1f;讓我們來回顧一下訓練神經網絡時出現的一些實際挑戰&#xff1a;首先&#xff0c;數據預處理的方式通常會對最終結果產生巨大影響。 回想一下我們應用多層感知機來預測房價的例子。使用真實數據時&#xff0c;我們的第一步是標準化輸入特征…

機器學習-支持向量機器(SVM)

0.1 數字識別 from sklearn.svm import SVC from sklearn.metrics import silhouette_score import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.feature_extraction import DictVectorizer from sk…

昆山PCB板工廠有哪些?

在長三角電子信息產業版圖中&#xff0c;昆山憑借完整的產業鏈配套和精湛的制造工藝&#xff0c;成為國內PCB&#xff08;印制電路板&#xff09;生產的重要基地。本文精選五家具有代表性的本土工廠&#xff0c;從技術實力到服務特色展開深度剖析&#xff0c;為行業客戶提供精準…

rk3588 ubuntu20.04安裝包經常出現的問題總結(chatgpt回復)

問題1 問題 我在rk3588 ubuntu20.04安裝相關環境的時候經常出現下面類似的問題&#xff0c;如何系統的解決 The following packages have unmet dependencies : openssh-server : Depends: openssh-client ( 1:8.2p1-4ubuntu0.13) but 1:8.2p1-4ubuntu0.11 is to be installed …

從根源到生態:Apache Doris 與 StarRocks 的深度對比 —— 論開源基因與長期價值的優越性

在 OLAP 領域&#xff0c;Apache Doris 與 StarRocks 常被一同提及&#xff0c;兩者有著深厚的技術淵源 ——StarRocks 源自 Apache Doris 的代碼 Fork&#xff0c;卻在后續發展中走向了不同的路徑。本文將從代碼根源、架構演進、社區生態、功能特性等多維度展開對比。 一、代…

【從零開始學習Redis】項目實戰-黑馬點評D1

項目實戰-黑馬點評 項目架構短信登錄發送短信驗證碼 實現思路就是按照上圖左一部分&#xff0c; 實現類如下 Slf4j Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** 驗證手機號發送驗證碼** param phone* pa…

自然語言處理的范式轉變:從Seq2Seq模型到Transformer架構

Seq2Seq 定義 Seq2Seq是一個Encoder-Decoder結構的網絡&#xff0c;它的輸入是一個序列&#xff0c;輸出也是一個序列&#xff0c; Encoder使用循環神經網絡(RNN,GRU&#xff0c;LSTM等)&#xff0c;將一個可變長度的信號序列(輸入句子)變為固定維度的向量編碼表達&#xff0c;…

【博客系統測試報告】---接口自動化測試

目錄 1、需求分析 2、挑選接口 3、設計博客系統的測試用例 4、設計自動化測試框架 test_add.py: test_detail.py: test_getAuthorInfo.py: test_getUserInfo: test_list.py: test_login.py: logger_util.py: request_util.py: yaml_util.py: 1、需求分析 根據業務…

Mysql數據庫遷移到GaussDB注意事項

mysql數據庫遷移高斯數據庫 建議開啟高斯數據庫M模式&#xff0c;mysql兼容模式&#xff0c;可以直接使用mysql的建表語句&#xff0c;自增主鍵可以使用AUTO_INCREMENT&#xff0c;如果不開啟M模式&#xff0c;只能使用高斯數據庫的序列添加自增主鍵1&#xff1a;如果使用數據庫…

蘋果正計劃大舉進軍人工智能硬件領域

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

Serverless 架構核心解析與應用實踐

Serverless 的核心定義與優勢??核心定義Serverless&#xff08;無服務器架構&#xff09;是一種云計算模型&#xff0c;開發者無需關注底層服務器管理&#xff0c;由云服務商自動分配資源、彈性擴縮容&#xff0c;并按實際使用量計費?。其核心特點包括&#xff1a;?按需計算…

Redis持久化機制詳解:RDB與AOF的全面對比與實踐指南

目錄 一、RDB持久化機制 1.1 RDB概述 1.2 RDB觸發機制 1) 手動執行save命令 2) 手動執行bgsave命令 3) Redis正常關閉時 4) 自動觸發條件滿足時 1.3 RDB詳細配置 1.4 RDB實現原理 1.5 RDB的優缺點分析 二、AOF持久化機制 2.1 AOF概述 2.2 AOF工作流程 2.3 AOF同步…

介紹一下jQuery的AJAX異步請求

目錄 一、核心方法&#xff1a;$.ajax() 二、簡化方法&#xff08;常用場景&#xff09; 1. $.get()&#xff1a;快速發送 GET 請求&#xff08;獲取數據&#xff09; 2. $.post()&#xff1a;快速發送 POST 請求&#xff08;提交數據&#xff09; 3. $.getJSON()&#xf…