力扣每日一題--2025.7.16

📚 力扣每日一題–2025.7.16

📚 3201. 找出有效子序列的最大長度 I(中等)

今天我們要解決的是力扣上的第 3201 題——找出有效子序列的最大長度 I。這道題雖然標記為中等難度,但只要掌握了正確的思路,就能輕松解決!

📝 題目描述

在這里插入圖片描述
在這里插入圖片描述

🤔 思路分析

核心需求推導過程 📝

題目要求子序列中所有相鄰元素之和的奇偶性必須相同,即:

(sub[0] + sub[1]) % 2 == (sub[1] + sub[2]) % 2 == ... == (sub[x-2] + sub[x-1]) % 2

這個條件可以從兩個角度理解:

  1. 數學本質:所有相鄰元素對的和具有相同的奇偶性
  2. 序列特性:子序列中的元素必須形成一種特定的奇偶性模式

通過進一步推理,我們可以得出兩種基本的有效序列模式:

模式一:全同奇偶性序列

  • 當要求相鄰元素之和為偶數時,所有元素必須具有相同的奇偶性
  • 證明:若 a+b 為偶數且 b+c 為偶數,則 a 和 b 奇偶性相同,b 和 c 奇偶性相同,因此 a 和 c 奇偶性相同,以此類推

模式二:交替奇偶性序列

  • 當要求相鄰元素之和為奇數時,元素必須交替出現奇偶性
  • 證明:若 a+b 為奇數且 b+c 為奇數,則 a 和 b 奇偶性不同,b 和 c 奇偶性不同,因此 a 和 c 奇偶性相同,形成交替模式

讓我們通過具體示例驗證這些模式:

  • 全奇序列 [1,3,5,7]:所有相鄰和都為偶數 (4,8,12),符合模式一
  • 奇偶交替序列 [1,2,3,4]:所有相鄰和都為奇數 (3,5,7),符合模式二
  • 混合序列 [1,2,2,3]:相鄰和為 3(奇)、4(偶)、5(奇),不符合任何模式

所以,有效子序列有兩種基本類型:

  1. 所有相鄰元素之和都為偶數
  2. 所有相鄰元素之和都為奇數

我們需要分別找出這兩種類型的最長子序列,然后取較大值作為答案。

📑 解法探討

方法一:暴力枚舉(理解問題本質)

最直觀的思路是枚舉所有可能的子序列,檢查它們是否有效,并記錄最長有效子序列的長度。

這個官方的測試用例可以通過,但是提交的時候會超時,我這邊只是給大家提供一個思路方法。

/*** 方法一:暴力枚舉法* 思路:枚舉所有可能的子序列起點和兩種類型的有效子序列,*       構建并檢查每個子序列的有效性,記錄最長有效子序列長度* 注意:此方法僅用于理解問題本質,實際提交可能會超時*/
public class Solution {/*** 找出最長有效子序列的長度* @param nums 輸入的整數數組* @return 最長有效子序列的長度*/public int maximumLength(int[] nums) {int n = nums.length;// 邊界情況處理:空數組或單元素數組,直接返回數組長度if (n <= 1) return n;// 最小有效子序列長度為1(單個元素本身就是有效子序列)int maxLen = 1;// 枚舉所有可能的子序列起點for (int i = 0; i < n; i++) {// 嘗試兩種類型的有效子序列// type=0: 相鄰元素之和為偶數// type=1: 相鄰元素之和為奇數for (int type = 0; type <= 1; type++) {int len = 1;          // 當前子序列長度,至少包含起點元素int last = nums[i];   // 記錄子序列最后一個元素// 從起點后一個元素開始構建子序列for (int j = i + 1; j < n; j++) {// 計算當前元素與子序列最后一個元素之和的奇偶性int sumMod = (last + nums[j]) % 2;// 如果符合當前類型要求,則加入子序列if (sumMod == type) {len++;last = nums[j]; // 更新子序列最后一個元素}}// 更新最長有效子序列長度maxLen = Math.max(maxLen, len);}}return maxLen;}
}

復雜度分析

  • 時間復雜度:O(n2),其中 n 是數組長度
  • 空間復雜度:O(1),只使用了常數額外空間
方法二:貪心算法(最優解法)

通過觀察,我們可以發現兩種類型的有效子序列具有明顯的模式:

  1. 類型 0(相鄰元素之和為偶數):所有元素必須具有相同的奇偶性

    • 全是偶數,或全是奇數
    • 最長長度 = max(偶數元素個數, 奇數元素個數)
  2. 類型 1(相鄰元素之和為奇數):元素必須交替出現奇偶性

    • 奇偶奇偶…或偶奇偶奇…
    • 最長長度取決于兩種模式中較長的一個

基于這些觀察,我們可以設計出 O(n)時間復雜度的貪心算法:

/*** 方法二:貪心算法(最優解法)* 思路:通過分析有效子序列的兩種模式,分別計算其最大長度*       類型0(相鄰和為偶數):所有元素奇偶性相同,取較多的那種奇偶性元素個數*       類型1(相鄰和為奇數):元素奇偶性交替出現,計算兩種起始模式的最大長度* 時間復雜度:O(n),空間復雜度:O(1)*/
public class Solution {/*** 找出最長有效子序列的長度* @param nums 輸入的整數數組* @return 最長有效子序列的長度*/public int maximumLength(int[] nums) {int n = nums.length;// 邊界情況處理:空數組或單元素數組,直接返回數組長度if (n <= 1) return n;// 統計數組中奇數和偶數的個數int oddCount = 0, evenCount = 0;for (int num : nums) {if (num % 2 == 0) evenCount++;else oddCount++;}// 類型0的最大長度:所有元素奇偶性相同,取較多的那種int type0Max = Math.max(oddCount, evenCount);// 如果只有一種奇偶性,無法形成類型1的子序列(需要交替出現)if (oddCount == 0 || evenCount == 0) {return type0Max;}// 計算類型1的兩種模式的最大長度// 模式1:以奇數開始的交替序列(奇-偶-奇-偶...)int type1Max1 = calculateAlternatingLength(nums, true);// 模式2:以偶數開始的交替序列(偶-奇-偶-奇...)int type1Max2 = calculateAlternatingLength(nums, false);// 取兩種模式中的較大值int type1Max = Math.max(type1Max1, type1Max2);// 返回兩種類型中的最大值return Math.max(type0Max, type1Max);}/*** 計算交替奇偶性序列的長度* @param nums 輸入的整數數組* @param startWithOdd 是否以奇數開始* @return 交替序列的長度*/private int calculateAlternatingLength(int[] nums, boolean startWithOdd) {int length = 0;               // 序列長度boolean expectedOdd = startWithOdd; // 期望的下一個元素的奇偶性// 遍歷數組,構建交替序列for (int num : nums) {boolean isOdd = num % 2 == 1; // 當前元素是否為奇數// 如果當前元素符合期望的奇偶性,則加入序列if (isOdd == expectedOdd) {length++;expectedOdd = !expectedOdd; // 切換期望的奇偶性}}return length;}
}

復雜度分析

  • 時間復雜度:O(n),只需遍歷數組幾次
  • 空間復雜度:O(1),只使用了常數額外空間
方法三:動態規劃(更通用的解決方案)

這個也超時了,但是方法思路應該是這樣的,之后我再想辦法去優化一下。

我們也可以使用動態規劃來解決這個問題,定義兩個狀態:

  • dp0[i]:以第 i 個元素結尾,且相鄰元素之和為偶數的最長有效子序列長度
  • dp1[i]:以第 i 個元素結尾,且相鄰元素之和為奇數的最長有效子序列長度
/*** 方法三:動態規劃(更通用的解決方案)* 思路:定義兩個狀態數組,分別記錄以每個位置結尾的兩種類型子序列的最大長度*       dp[i][0]:以第i個元素結尾,相鄰和為偶數的最長子序列長度*       dp[i][1]:以第i個元素結尾,相鄰和為奇數的最長子序列長度* 時間復雜度:O(n2),空間復雜度:O(n)*/
public class Solution {/*** 找出最長有效子序列的長度* @param nums 輸入的整數數組* @return 最長有效子序列的長度*/public int maximumLength(int[] nums) {int n = nums.length;// 邊界情況處理:空數組或單元素數組,直接返回數組長度if (n <= 1) return n;// 動態規劃數組定義:// dp[i][0]:以第i個元素結尾,且相鄰元素之和為偶數的最長有效子序列長度// dp[i][1]:以第i個元素結尾,且相鄰元素之和為奇數的最長有效子序列長度int[][] dp = new int[n][2];// 初始化:第一個元素本身就是長度為1的有效子序列dp[0][0] = 1; // 以第一個元素結尾的類型0子序列dp[0][1] = 1; // 以第一個元素結尾的類型1子序列int maxLen = 1; // 記錄最長有效子序列長度// 從第二個元素開始計算for (int i = 1; i < n; i++) {// 默認情況下,子序列只包含當前元素,長度為1dp[i][0] = 1;dp[i][1] = 1;// 檢查前面所有元素,看是否可以形成更長的有效子序列for (int j = 0; j < i; j++) {// 計算nums[j]和nums[i]之和的奇偶性int sumMod = (nums[j] + nums[i]) % 2;// 如果前面元素j和當前元素i的和的奇偶性為sumMod// 則可以將i添加到以j結尾的sumMod類型子序列后面if (dp[j][sumMod] + 1 > dp[i][sumMod]) {dp[i][sumMod] = dp[j][sumMod] + 1;}}// 更新最長有效子序列長度maxLen = Math.max(maxLen, Math.max(dp[i][0], dp[i][1]));}return maxLen;}
}

復雜度分析

  • 時間復雜度:O(n2),其中 n 是數組長度
  • 空間復雜度:O(n),需要存儲 dp 數組

🚀 優化后的貪心算法

我們可以進一步優化貪心算法,只需要一次遍歷就能計算出兩種類型 1 子序列的最大長度:

/*** 方法四:優化后的貪心算法* 思路:在基礎貪心算法的基礎上,通過一次遍歷同時計算兩種類型1子序列的長度*       減少了遍歷次數,進一步優化了性能* 時間復雜度:O(n),空間復雜度:O(1)*/
public class Solution {/*** 找出最長有效子序列的長度* @param nums 輸入的整數數組* @return 最長有效子序列的長度*/public int maximumLength(int[] nums) {int n = nums.length;// 邊界情況處理:空數組或單元素數組,直接返回數組長度if (n <= 1) return n;// 統計數組中奇數和偶數的個數int oddCount = 0, evenCount = 0;for (int num : nums) {if (num % 2 == 0) evenCount++;else oddCount++;}// 類型0的最大長度:所有元素奇偶性相同,取較多的那種int type0Max = Math.max(oddCount, evenCount);// 如果只有一種奇偶性,無法形成類型1的子序列(需要交替出現)if (oddCount == 0 || evenCount == 0) {return type0Max;}// 一次遍歷同時計算兩種類型1子序列的最大長度int type1OddStart = 0;  // 以奇數開始的交替序列長度(奇-偶-奇-偶...)int type1EvenStart = 0; // 以偶數開始的交替序列長度(偶-奇-偶-奇...)boolean expectOddForOddStart = true;  // 奇開始模式下期望的下一個奇偶性boolean expectOddForEvenStart = false; // 偶開始模式下期望的下一個奇偶性// 遍歷數組,同時構建兩種交替模式的子序列for (int num : nums) {boolean isOdd = num % 2 == 1; // 當前元素是否為奇數// 處理奇-偶-奇-偶...模式if (isOdd == expectOddForOddStart) {type1OddStart++;expectOddForOddStart = !expectOddForOddStart; // 切換期望的奇偶性}// 處理偶-奇-偶-奇...模式if (isOdd == expectOddForEvenStart) {type1EvenStart++;expectOddForEvenStart = !expectOddForEvenStart; // 切換期望的奇偶性}}// 類型1的最大長度為兩種模式中的較大值int type1Max = Math.max(type1OddStart, type1EvenStart);// 返回兩種類型中的最大值return Math.max(type0Max, type1Max);}
}

復雜度分析

  • 時間復雜度:O(n),只需一次遍歷
  • 空間復雜度:O(1),只使用了常數額外空間

🔍 算法執行流程可視化

開始
統計奇數和偶數個數
計算類型0最大長度
是否同時有奇數和偶數?
返回類型0最大長度
計算兩種類型1子序列長度
比較類型0和類型1的最大值
返回最終結果

📊 示例分析

讓我們通過幾個示例來理解算法的工作原理:

示例 1:nums = [1,2,3,4,5]

  • 奇數: 1,3,5 (count=3)
  • 偶數: 2,4 (count=2)
  • 類型 0 最大長度: max(3,2)=3
  • 類型 1(奇-偶-奇-偶…): 1,2,3,4,5 → 長度 5
  • 類型 1(偶-奇-偶-奇…): 2,3,4,5 → 長度 4
  • 最終結果: max(3,5)=5

示例 2:nums = [1,3,5,7]

  • 奇數: 1,3,5,7 (count=4)
  • 偶數: 0 (count=0)
  • 無法形成類型 1 子序列
  • 最終結果: 4

示例 3:nums = [1,2,2,2,2]

  • 奇數: 1 (count=1)
  • 偶數: 2,2,2,2 (count=4)
  • 類型 0 最大長度: max(1,4)=4
  • 類型 1(奇-偶-奇-偶…): 1,2 → 長度 2
  • 類型 1(偶-奇-偶-奇…): 2 → 長度 1
  • 最終結果: max(4,2)=4

💡 拓展思考

問題變體
  1. 如果要求子序列中相鄰元素之和的余數等于某個特定值 k(而不只是所有余數相等),該如何解決?(這個是緊挨著的 力扣3202 題)
  2. 如果允許子序列中有一個"錯誤"(即有一處相鄰元素之和的余數與其他不同),最長有效子序列的長度會是多少?
實際應用

這個問題在信號處理和模式識別中有實際應用。例如,在分析時間序列數據時,我們可能需要找到具有特定模式的最長子序列。

算法選擇策略
  • 對于小規模數據,任何算法都能勝任
  • 對于大規模數據,貪心算法是最佳選擇,因為它具有 O(n)時間復雜度
  • 動態規劃方法雖然復雜度較高,但具有更好的通用性,可以解決更復雜的變體問題

📝 總結

本題考察了對子序列概念的理解以及貪心算法的應用。通過分析相鄰元素之和的奇偶性規律,我們發現有效子序列有兩種基本類型,并分別計算了它們的最大長度。

貪心算法是解決本題的最優選擇,它基于以下關鍵洞察:

  1. 類型 0 子序列要求所有元素具有相同的奇偶性
  2. 類型 1 子序列要求元素的奇偶性交替出現

通過計算這兩種類型的最大長度并取較大值,我們得到了問題的解。

希望今天的講解能幫助你更好地理解這個問題和貪心算法的應用!如果你有任何疑問或想法,歡迎在評論區留言討論。明天見!👋

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

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

相關文章

SFT:大型語言模型專業化定制的核心技術體系——原理、創新與應用全景

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 以下基于權威期刊、會議論文及技術報告&#xff0c;對監督微調&#x…

若依前后端分離框架配置多數據庫表

若依前后端分離框架配置多數據庫表1、配置application.yml2、注釋掉application-druid.yml中的數據庫3、在DataSourceType 中添加新增的數據庫來源4、配置DruidConfig文件4、1新增注入方法&#xff0c;在DataSourceType類添加數據源枚舉4、2在DruidConfig類dataSource方法添加數…

29.安卓逆向2-frida hook技術-逆向os文件(二)IDA工具下載和使用(利用ai分析so代碼)

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a;圖靈Python學院 工具下載&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…

[析]Deep reinforcement learning for drone navigation using sensor data

Deep reinforcement learning for drone navigation using sensor data 基于傳感器數據的無人機導航深度強化學習方法 評價&#xff1a;MDP無記憶性&#xff0c;使用LSTM補足缺點。PPO解決新舊策略差距大的問題。 對于環境中的障礙物&#xff0c;設置增量課程&#xff0c;障礙…

SpringBoot項目啟動報:java: 找不到符號 符號: 變量 log 的解決辦法

問題&#xff1a;使用IDEA創建SpringBoot項目&#xff0c;在項目中使用 Slf4j 注解引入log日志后&#xff0c;啟動項目&#xff0c;報如下錯誤&#xff1a;原因&#xff1a;網上找了很多博文&#xff0c;說是lombook依賴沒有引入&#xff0c;但是我的pom.xml中已經引入 lombook…

HTML基礎知識 二(創建容器和表格)

HTML 基礎知識&#xff1a;創建容器和表格&#xff08;補充版&#xff09;HTML&#xff08;超文本標記語言&#xff09;是構建網頁的基礎。容器元素用于組織內容&#xff0c;表格用于展示結構化數據&#xff0c;兩者都是網頁設計中不可或缺的部分。一、HTML 容器元素容器元素就…

多目標優化|HKELM混合核極限學習機+NSGAII算法工藝參數優化、工程設計優化,四目標(最大化輸出y1、最小化輸出y2,y3,y4),Matlab完整源碼

基本介紹 1.HKELM混合核極限學習機NSGAII多目標優化算法&#xff0c;工藝參數優化、工程設計優化&#xff01;&#xff08;Matlab完整源碼和數據&#xff09; 多目標優化是指在優化問題中同時考慮多個目標的優化過程。在多目標優化中&#xff0c;通常存在多個沖突的目標&#x…

【AI智能體】Dify 基于知識庫搭建智能客服問答應用詳解

目錄 一、前言 二、Dify 介紹 2.1 Dify 核心特點 三、AI智能體構建智能客服系統介紹 3.1 基于AI智能體平臺搭建智能客服系統流程 3.1.1 需求分析與場景設計 3.1.2 選擇合適的AI智能體平臺 3.1.3 工作流編排與調試 3.1.4 系統集成與發布 3.2 使用AI智能體構建智能客服系…

事務~~~

1、四大特性&#xff1a;A 原子性&#xff1a;對數據的一組操作&#xff0c;要么執行成功&#xff0c;要么不執行C 一致性&#xff1a;事務前后的狀態要保持一致&#xff0c;可以理解為數據的一致性I 隔離性&#xff1a;多個事務之間是隔離的&#xff0c;互不影響D 持久性&…

【Linux編譯】./build.sh: line 17: $‘\r‘: command not found

文章目錄0.運行編譯腳本遇到問題&#xff1a;方法 1&#xff1a;使用 dos2unix&#xff08;推薦&#xff09;1. 安裝 dos2unix2. 遞歸轉換整個目錄方法 2&#xff1a;使用 sed&#xff08;無需安裝額外工具&#xff09;方法 3&#xff1a;使用 tr&#xff08;僅單文件&#xff…

Weblogic歷史漏洞利用

文章目錄漏洞介紹WebLogic 漏洞概述歷史漏洞利用弱口令CVE-2014-4210CVE-2018-2894CVE-2019-2725CVE-2020-14882漏洞介紹 Oracle WebLogic Server 是一個用于開發和部署企業級 Java 應用的服務器平臺&#xff0c;但其歷史上存在多個嚴重漏洞&#xff0c;尤其以遠程代碼執行&am…

[Rust 基礎課程]使用 Cargo 創建 Hello World 項目

Cargo&#xff08;https://crates.io/&#xff09; 是 Rust 語言中最常用的構建工具和包管理工具&#xff0c;我們看看怎么通過 Cargo 創建一個 Hello World 項目并運行。 :::warning 通過官方的 Rust 安裝方式安裝 Rust&#xff0c;Cargo 是同時默認安裝好的了 ::: 首先&am…

C語言 --- 函數遞歸

函數遞歸一、什么是函數遞歸二、函數遞歸的要點三、示例1.計算n的階乘2.提取一個任意正整數的所有位數&#xff0c;按順序排列3.獲取第n個斐波那契數&#xff0c;最開始的兩個數是1&#xff0c;1四、總結一、什么是函數遞歸 函數遞歸是一種解決問題的思想&#xff0c;是將一個…

GitHub 趨勢日報 (2025年07月14日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖1916claude-code795the-book-of-secret-knowledge728free-for-dev547markitdown367…

PyTorch中張量(TensorFlow)操作方法和屬性匯總詳解和代碼示例

1、張量的操作匯總 下面是 PyTorch 中常見的 張量操作方法匯總&#xff0c;包括 創建、索引、變換、數學運算、廣播機制、維度操作 等內容&#xff0c;并附上詳解和代碼示例&#xff0c;便于系統學習與實戰參考。一、張量創建&#xff08;torch.tensor 等&#xff09; import t…

統一日志格式規范與 Filebeat+Logstash 實踐落地

背景 在多部門、多技術棧并存的企業環境中&#xff0c;日志收集與分析是保障系統穩定運行的核心能力之一。然而&#xff0c;不同開發團隊采用各異的日志打印方式&#xff0c;導致日志數據結構混亂&#xff0c;嚴重影響后續的收集、存儲、檢索與告警效率。 比如我們大部門就有多…

【鴻蒙HarmonyOS】鴻蒙app開發入門到實戰教程(三):實現一個音樂列表的頁面

鴻蒙里面&#xff0c;實現一個音樂播放的列表,模擬數組的數據展示 實現效果代碼實現 準備數據 songs:SongItemTypes[] [{img:https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.jpg,name:直到世界的盡頭,author:WANDS},{img:https://yjy-teach-oss.oss-cn…

2025年滲透測試面試題總結-2025年HW(護網面試) 47(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 2025年HW(護網面試) 47 1. UDF提權 2. 命令執行與代碼執行的區別 3. 文件包含利用姿勢 4. 漏洞復現流程 …

iPhone 數據擦除軟件評測(最新且全面)

當您準備出售、捐贈或回收 iPhone 時&#xff0c;僅僅恢復出廠設置并不足以保證您的個人數據徹底消失。專業的 iPhone 數據擦除軟件采用先進的技術&#xff0c;確保您的敏感信息永久無法恢復。本文回顧了十種流行的 iPhone 數據擦除工具&#xff0c;詳細介紹了它們的功能、優點…

Qt 將觸摸事件轉換為鼠標事件(Qt4和Qt5及以上版本)

在Qt中&#xff0c;觸摸事件&#xff08;QTouchEvent&#xff09;和鼠標事件&#xff08;QMouseEvent&#xff09;是兩種不同的輸入事件類型。通常情況下&#xff0c;觸摸事件不會自動轉換為鼠標事件&#xff0c;因為它們代表的是不同的輸入設備&#xff08;觸摸屏 vs 鼠標&…