【LeetCode每日一題】

每日一題

  • 3. 無重復字符的最長子串
    • 題目
    • 總體思路
    • 代碼
  • 1.兩數之和
    • 題目
    • 總體思路
    • 代碼
  • 15. 三數之和
    • 題目
    • 總體思路
    • 代碼

2025.8.15

3. 無重復字符的最長子串

題目

給定一個字符串 s ,請你找出其中不含有重復字符的 最長 子串 的長度。

示例 1:
輸入: s = “abcabcbb”
輸出: 3
解釋: 因為無重復字符的最長子串是 “abc”,所以其長度為 3。
示例 2:
輸入: s = “bbbbb”
輸出: 1
解釋: 因為無重復字符的最長子串是 “b”,所以其長度為 1。
示例 3:
輸入: s = “pwwkew”
輸出: 3
解釋: 因為無重復字符的最長子串是 “wke”,所以其長度為 3。
請注意,你的答案必須是 子串 的長度,“pwke” 是一個子序列,不是子串。

提示:
0 <= s.length <= 5 * 104
s 由英文字母、數字、符號和空格組成

總體思路

用布爾數組的滑動窗口法

  • 使用固定大小數組標記字符是否出現過:
    這里 visited[128] 對應 ASCII 碼字符。
    true 表示該字符在當前窗口內已經出現。
  • 維護滑動窗口:
    left 表示窗口左邊界,right 表示窗口右邊界。
    窗口 [left, right] 中保證沒有重復字符。
  • 遇到重復字符時移動左指針:
    如果 visited[ch] == true,說明當前字符已在窗口中。
    移動左指針 left,同時將左邊字符標記清除,直到窗口中不再有重復字符。
  • 更新窗口狀態:
    將當前字符 ch 標記為已出現。
    更新 maxLen 為窗口長度 right-left+1。
  • 時間復雜度:
    每個字符最多進出窗口一次 → O(n)
    空間復雜度 O(1),因為固定數組大小 128。

用哈希表的滑動窗口法

  • 使用哈希表記錄窗口中字符出現次數:
    鍵是字符,值是出現次數(這里最多是 1)。
    動態維護當前窗口的字符集合。
  • 維護滑動窗口的左右指針:
    i 是左指針,rk 是右指針。
    左指針每移動一次,移除窗口最左邊的字符。
    右指針盡可能右移,保證窗口內沒有重復字符。
  • 右指針移動條件:
    rk+1 < n 防止越界
    m[s[rk+1]] == 0 窗口中沒有重復字符
    滿足條件時,右指針 rk 右移,并將字符計入哈希表。
  • 更新答案:
    窗口 [i, rk] 是以 i 為左邊界的最長無重復字符子串
    ans = max(ans, rk-i+1)。
  • 時間復雜度:
    每個字符進出窗口一次 → O(n)
    空間復雜度 O(min(n, charset)),因為哈希表動態存儲字符。

代碼

golang

// 使用滑動窗口法查找無重復字符的最長子串長度
func lengthOfLongestSubstring(s string) int {visited := [128]bool{} // ASCII 碼范圍的字符標記數組left, maxLen := 0, 0for right := 0; right < len(s); right++ {ch := s[right]// 如果當前字符已經在窗口內出現過,則移動左指針直到移除該字符for visited[ch] {visited[s[left]] = falseleft++}// 標記該字符已出現visited[ch] = true// 更新最大長度if right-left+1 > maxLen {maxLen = right - left + 1}}return maxLen
}func lengthOfLongestSubstring(s string) int {// 哈希表,記錄窗口中字符出現次數m := map[byte]int{}n := len(s) // 字符串長度// 右指針,初始值為 -1// 相當于在字符串左邊界左側,還沒有開始移動rk, ans := -1, 0// 遍歷每個字符,i 是左指針for i := 0; i < n; i++ {if i != 0 {// 左指針向右移動一格// 移除窗口最左邊的字符delete(m, s[i-1])}// 不斷向右移動右指針 rk// 條件:// 1. rk+1 < n,防止越界// 2. m[s[rk+1]] == 0,窗口中沒有重復字符for rk+1 < n && m[s[rk+1]] == 0 {rk++              // 右指針右移一格m[s[rk]]++        // 把該字符加入窗口}// 此時窗口 [i, rk] 是一個最長無重復字符子串// 更新答案ans = max(ans, rk-i+1)}return ans
}

1.兩數之和

題目

給定一個整數數組 nums 和一個整數目標值 target,請你在該數組中找出 和為目標值 target 的那 兩個 整數,并返回它們的數組下標。
你可以假設每種輸入只會對應一個答案,并且你不能使用兩次相同的元素。
你可以按任意順序返回答案。

示例 1:
輸入:nums = [2,7,11,15], target = 9
輸出:[0,1]
解釋:因為 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
輸入:nums = [3,2,4], target = 6
輸出:[1,2]
示例 3:
輸入:nums = [3,3], target = 6
輸出:[0,1]

提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只會存在一個有效答案

總體思路

暴力求解法

  • 枚舉所有可能的兩個數:
    用兩層 for 循環,第一層遍歷第一個數 nums[i],第二層遍歷第二個數 nums[j]。
  • 檢查是否滿足條件:
    如果 nums[i] + nums[j] == target 并且 i != j,說明找到了一對符合條件的下標。
  • 立即返回結果:
    直接返回這兩個下標 [i, j]。
  • 時間復雜度:
    外層循環 O(n),內層循環 O(n) → 總體 O(n2)。
    空間復雜度 O(1),因為沒有額外的數據結構。

哈希表優化法

  • 使用哈希表記錄已訪問過的數值:
    建一個 map[int]int,鍵是數值,值是該數值在 nums 中的下標。
  • 單次遍歷尋找匹配:
    遍歷 nums 時,對于當前數 num,計算它的“互補數” target - num。
  • 檢查互補數是否已出現過:
    如果互補數在哈希表中,說明之前某個元素的值 + 當前值正好等于 target,直接返回這兩個下標。
  • 否則記錄當前數:
    把當前的 (數值 → 下標) 存進哈希表,供后續元素匹配。
  • 時間復雜度:
    僅需單次遍歷 O(n)。
    空間復雜度 O(n),用來存儲哈希表。

代碼

golang

//暴力求解
func twoSum(nums []int, target int) []int {for i:=0;i<len(nums);i++{for j:=1;j<len(nums);j++{if nums[i]+nums[j]==target && i!=j{return []int{i,j}}}}return nil
} //哈希
func twoSum(nums []int, target int) []int {hash:=map[int]int{}   //鍵為“某個數值”,值為“該數值在 nums 中的下標”。for i, num:=range nums {   //range 遍歷切片,i 是下標,num 是當前元素的拷貝if p, ok :=hash[target-num];ok{   //互補數是否已經出現過。如果出現過,ok == true,p 是互補數的下標。return []int{p,i}}hash[num]=i   //把“當前數值 → 當前下標”記進表里,供后面的元素來匹配。}return nil
}

2025.8.16

15. 三數之和

題目

給你一個整數數組 nums ,判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i != j、i != k 且 j != k ,同時還滿足 nums[i] + nums[j] + nums[k] == 0 。請你返回所有和為 0 且不重復的三元組。
注意:答案中不可以包含重復的三元組。

示例 1:
輸入:nums = [-1,0,1,2,-1,-4]
輸出:[[-1,-1,2],[-1,0,1]]
解釋:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元組是 [-1,0,1] 和 [-1,-1,2] 。
注意,輸出的順序和三元組的順序并不重要。
示例 2:
輸入:nums = [0,1,1]
輸出:[]
解釋:唯一可能的三元組和不為 0 。
示例 3:
輸入:nums = [0,0,0]
輸出:[[0,0,0]]
解釋:唯一可能的三元組和為 0 。

提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105

總體思路

雙指針法

  • 排序
    先對數組 nums 排序。
    排序后可以利用雙指針移動來快速縮小范圍。
  • 固定第一個數 nums[i]
    從左到右依次枚舉 i。
    如果 nums[i] > 0,因為數組已經排序,后面的數都 ≥0,不可能再湊出 0,可以直接停止。
    如果 nums[i] 跟前一個數相同,就跳過,避免重復解。
  • 左右指針搜索另外兩個數
    設定 left := i+1,right := n-1。
    計算三數之和 sum := nums[i] + nums[left] + nums[right]。
    • 如果 sum == 0,說明找到一組解。
      保存三元組 [nums[i], nums[left], nums[right]]。
      然后移動 left++ 和 right–,并且跳過重復值。
    • 如果 sum < 0,說明和太小,需要增大和 → left++。
    • 如果 sum > 0,說明和太大,需要減小和 → right–。
  • 繼續枚舉下一個 i
    直到遍歷完成,返回所有解。

暴力求解(三重循環)

  • 枚舉所有三元組
    用三層循環,依次固定下標 i、j、k,保證它們互不相等。
    枚舉所有可能的組合 (nums[i], nums[j], nums[k])。
  • 判斷和是否為 0
    如果 nums[i] + nums[j] + nums[k] == 0,就認為它是一個符合要求的三元組。
  • 避免重復
    直接三重循環會出現重復解,比如 [?1,0,1] 可能通過不同的下標組合出現多次。
    常見做法是:
    • 先對數組排序。
    • 再用一個 map 或 set(在 Go 里用 map[[3]int]bool)來記錄已經出現過的三元組。
  • 保存結果:
    把符合條件的三元組存入結果切片 [][]int,最后返回。

代碼

golang

//雙指針
import "sort"
func threeSum(nums []int) [][]int {sort.Ints(nums)  //排序n := len(nums)//left, right := 1, len(nums)-1ret := make([][]int, 0)seen := make(map[[3]int]bool)for i:=0; i<n-2; i++ {// 如果 nums[i] > 0,后面全是非負數,不可能和為0,直接breakif nums[i] > 0 {break}// 跳過重復的i,避免結果重復if i > 0 && nums[i] == nums[i-1] {continue}left, right := i+1, n-1for left<right {sum := nums[i] + nums[left] + nums[right]if sum == 0 {key:=[3]int{nums[i],nums[left],nums[right]}if !seen[key] {seen[key]=trueret = append(ret,[]int{nums[i],nums[left],nums[right]})}left++right--}else if sum < 0 {left++ // 和偏小,左指針右移} else {right-- // 和偏大,右指針左移}}}return ret}//暴力求解超時了。。。bunengyong
import "sort"
func threeSum(nums []int) [][]int {sort.Ints(nums)    //先排序,便于存入集合時用有序三元組作為去重鍵res := make([][]int, 0)// 使用 map 記錄已經出現過的三元組(用固定順序的[3]int作為key)seen :=make(map[[3]int]bool)for i:=0;i<len(nums)-2;i++ {for j:=i+1;j<len(nums)-1;j++ {for k:=j+1;k<len(nums);k++ {if(nums[i]+nums[j]+nums[k]==0){key := [3]int{nums[i],nums[j],nums[k]}//去重if !seen[key]{   seen[key]=trueres = append(res, []int{nums[i], nums[j], nums[k]})}}}}}return res
}

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

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

相關文章

sharding-jdbc讀寫分離配置

一主兩從&#xff0c;爆紅是正常的&#xff0c;不知為啥 spring:shardingsphere:datasource:names: ds_master,ds_s1,ds_s2ds_master:type: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.135.100:3306/gmall_produ…

【大模型核心技術】Dify 入門教程

文章目錄一、Dify 是什么二、安裝與部署2.1 云端 SaaS 版&#xff08;快速入門&#xff09;2.2 私有化部署&#xff08;企業級方案&#xff09;三、界面導航與核心模塊3.1 控制臺概覽3.2 核心功能模塊詳解3.2.1 知識庫&#xff08;RAG 引擎&#xff09;3.2.2 工作流編排3.2.3 模…

homebrew 1

文章目錄brew(1) – macOS&#xff08;或 Linux&#xff09;上缺失的包管理器概要描述術語表基本命令install *formula*uninstall *formula*listsearch \[*text*|/*text*/]命令alias \[--edit] \[*alias*|*alias**command*]analytics \[*subcommand*]autoremove \[--dry-run]bu…

設計索引的原則有哪些?

MySQL 索引設計的核心原則是 在查詢性能與存儲成本之間取得平衡。以下是經過實踐驗證的 10 大設計原則及具體實現策略&#xff1a;一、基礎原則原則說明示例/反例1. 高頻查詢優先為 WHERE、JOIN、ORDER BY、GROUP BY 頻繁出現的列建索引? SELECT * FROM orders WHERE user_id1…

使用影刀RPA實現快遞信息抓取

最近公司項目有個需求&#xff0c;要求抓取快遞單號快遞信息&#xff0c;比如簽收地點、簽收日期等。該項目對應的快遞查詢網站是一個國外的網站&#xff0c;他們有專門的快遞平臺可以用于查詢。該平臺提供了快遞接口進行查詢&#xff0c;但需要付費。同時也提供了免費的查詢窗…

蟻劍--安裝、使用

用途限制聲明&#xff0c;本文僅用于網絡安全技術研究、教育與知識分享。文中涉及的滲透測試方法與工具&#xff0c;嚴禁用于未經授權的網絡攻擊、數據竊取或任何違法活動。任何因不當使用本文內容導致的法律后果&#xff0c;作者及發布平臺不承擔任何責任。滲透測試涉及復雜技…

Varjo XR虛擬現實軍用車輛駕駛與操作培訓

Patria基于混合現實的模擬器提供了根據現代車輛乘員需求定制的培訓&#xff0c;與傳統顯示設置相比&#xff0c;全新的模擬解決方案具有更好的沉浸感和更小的物理空間需求。Patria是芬蘭領先的國防、安全和航空解決方案提供商。提供尖端技術和全面的培訓系統&#xff0c;以支持…

Java 10 新特性及具體應用

目錄 1. 局部變量類型推斷&#xff08;JEP 286&#xff09; 2. 不可修改集合&#xff08;JEP 269&#xff09; 3. 并行全垃圾回收&#xff08;JEP 307&#xff09; 4. 應用類數據共享&#xff08;JEP 310&#xff09; 5. 線程局部管控&#xff08;JEP 312&#xff09; 總結…

【力扣 Hot100】刷題日記

D8 全排列(非回溯法) 全排列原題鏈接 在刷leetcode的時候&#xff0c;看到這道題目并沒法使用像STL的next_permutation方法&#xff0c;感嘆C便利的同時&#xff0c;又惋惜Java并沒有類似的API&#xff0c;那我們只能從原理入手了&#xff0c;仿寫此算法。 其實回溯法更應該…

JetPack系列教程(七):Palette——讓你的APP色彩“飛”起來!

JetPack系列教程&#xff08;七&#xff09;&#xff1a;Palette——讓你的APP色彩“飛”起來&#xff01; 各位開發小伙伴們&#xff0c;還在為APP的配色發愁嗎&#xff1f;別擔心&#xff0c;今天咱們就來聊聊JetPack家族里的“色彩魔法師”——Palette&#xff01;這個神奇的…

力扣hot100 | 矩陣 | 73. 矩陣置零、54. 螺旋矩陣、48. 旋轉圖像、240. 搜索二維矩陣 II

73. 矩陣置零 力扣題目鏈接 給定一個 m x n 的矩陣&#xff0c;如果一個元素為 0 &#xff0c;則將其所在行和列的所有元素都設為 0 。請使用 原地 算法。 示例 1&#xff1a; 輸入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 輸出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]…

ARC與eARC是什么?主要用在哪?

在家庭影音設備不斷升級的今天&#xff0c;人們對音視頻體驗的要求越來越高。無論是追劇、玩游戲還是觀看電影大片&#xff0c;很多用戶不再滿足于電視自帶的揚聲器&#xff0c;而是希望借助回音壁、功放或家庭影院系統&#xff0c;獲得更加震撼的沉浸式聲音體驗。一、ARC是什么…

解鎖JavaScript性能優化:從理論到實戰

文章目錄 前言 一、常見性能瓶頸剖析 二、實戰案例與優化方案 (一)DOM 操作優化案例? (二)事件綁定優化案例? (三)循環與遞歸優化案例? (四)內存管理優化案例? 三、性能優化工具介紹 總結 前言 性能優化的重要性 在當今數字化時代,Web 應用已成為人們生活和工作…

結構化記憶、知識圖譜與動態遺忘機制在醫療AI中的應用探析(上)

往期相關內容推薦: 基于Python的多元醫療知識圖譜構建與應用研究(上)

XSS攻擊:從原理入門到實戰精通詳解

一、XSS攻擊基礎概念1.1 什么是XSS攻擊 XSS&#xff08;Cross-Site Scripting&#xff0c;跨站腳本攻擊&#xff09;是一種將惡意腳本注入到可信網站中的攻擊手段。當用戶訪問被注入惡意代碼的頁面時&#xff0c;瀏覽器會執行這些代碼&#xff0c;導致&#xff1a;用戶會話被劫…

Leetcode 14 java

今天復習一下以前做過的題目&#xff0c;感覺是忘光了。 160. 相交鏈表 給你兩個單鏈表的頭節點 headA 和 headB &#xff0c;請你找出并返回兩個單鏈表相交的起始節點。如果兩個鏈表不存在相交節點&#xff0c;返回 null 。 圖示兩個鏈表在節點 c1 開始相交&#xff1a; 題目數…

用 FreeMarker 動態構造 SQL 實現數據透視分析

在 ERP、BI 等系統中&#xff0c;數據透視分析&#xff08;Pivot Analysis&#xff09;是非常常見的需求&#xff1a;用戶希望按任意維度&#xff08;如門店、時間、商品分類等&#xff09;進行分組統計&#xff0c;同時選擇不同的指標&#xff08;如 GMV、訂單數、客單價等&am…

13.深度學習——Minst手寫數字識別

第一部分——起手式 import torch from torchvision import datasets, transforms import torch.nn as nn import torch.nn.functional as F import torch.optim as optimuse_cuda torch.cuda.is_available()if use_cuda:device torch.device("cuda") else: device…

【JAVA高級】實現word轉pdf 實現,源碼概述。深坑總結

之前的需求做好后,需求,客戶突發奇想。要將生成的word轉為pdf! 因為不想讓下載文檔的人改動文檔。 【JAVA】實現word添加標簽實現系統自動填入字段-CSDN博客 事實上這個需求難度較高,并不是直接轉換就行的 word文檔當中的很多東西都需要處理 public static byte[] gener…

數據驅動測試提升自動化效率

測試工程師老王盯著滿屏重復代碼嘆氣&#xff1a;“改個搜索條件要重寫20個腳本&#xff0c;這班加到啥時候是個頭&#xff1f;” 隔壁組的小李探過頭&#xff1a;“試試數據驅動唄&#xff0c;一套腳本吃遍所有數據&#xff0c;我們組上周測了300個組合都沒加班&#xff01;”…