LeetCode刷題 -- 20200607 首碼和篇

来源:https://www.cnblogs.com/dogtwo0214/archive/2020/06/07/13059236.html
-Advertisement-
Play Games

最近刷題倒是沒停,但是感覺大部分遇到的不是很適合拿來水博客,畢竟方法套路比較相似。年兄推薦下做了兩道首碼和的題,感覺這類題型的思路很棒,也可以歸納成一個方法,故再來水一篇。題目均來自力扣Leetcode,傳送門。 簡單來說,首碼和適合於解決 連續,求和 相關的問題。遇到的問題如果包含相關要求,可以考 ...


  最近刷題倒是沒停,但是感覺大部分遇到的不是很適合拿來水博客,畢竟方法套路比較相似。年兄推薦下做了兩道首碼和的題,感覺這類題型的思路很棒,也可以歸納成一個方法,故再來水一篇。題目均來自力扣Leetcode,傳送門

  簡單來說,首碼和適合於解決 連續,求和 相關的問題。遇到的問題如果包含相關要求,可以考慮嘗試一下首碼和的解法。諸如子數組的哈,連續幾個數字的和,等等。

 

974. 和可被 K 整除的子數組

示例:

輸入:A = [4,5,0,-2,-3,1], K = 5
輸出:7
解釋:
有 7 個子數組滿足其元素之和可被 K = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
 

提示:

1 <= A.length <= 30000
-10000 <= A[i] <= 10000
2 <= K <= 10000

 

  如題目描述,根據給定的數組我們需要尋找到它的子數組滿足條件 ==》子數組所有數字的和可以被K整除。註意這裡有個隱含條件,子數組的每一項的索引是連續的。

  假設一組數組每一項的值都和它的下標相同:

    • Sumx = 1 + 2 + 3 + ... + x
    • Sumy = 1 + 2 + 3 + ... + y

   這裡不妨假設y>x, 那麼 Sumy - Sumx = (x+1) + (x+2) + ... y 。這裡Sumy - Sumx 就是數組從x到y的和,我們要尋找的就是 (Sumy - Sumx ) % K = 0的子數組。因此可以轉化為Sumy % K == Sumx % K的首碼和表達。而首碼和其實我們是可以通過一次遍歷就獲得的,只需要一個變數輔助記錄上一個位置的首碼和即可。

  現在我們的題目轉化為了求得Sumy % K == Sumx % K的子數組的個數,並且也知道了怎麼計算首碼和。現在只需要使用Hash表來記錄首碼和出現的次數即可。當hash表中出現了Key相同的元素,說明我們遇到了首碼和相同,即符合條件的子數組。註意這裡同時也要更新一下Hash表中的數據。

  註意對於這道題來說,負數需要特別處理一下。來看看代碼吧:

 1 public class Solution {
 2         public int SubarraysDivByK(int[] A, int K)
 3         {
 4             int result = 0;
 5             List<int> preSum = new List<int>();
 6             preSum.Add(0);
 7 
 8             Dictionary<int, int> dict = new Dictionary<int, int>();
 9             dict.Add(0, 1);
10 
11             for (int i = 0; i < A.Length; i++)
12             {
13                 preSum.Add(preSum[i] + A[i]);
14                 int temp = preSum[i + 1] % K;
15                 temp = temp < 0 ? temp + K : temp;
16 
17                 if (dict.Keys.Contains(temp))
18                 {
19                     result += dict[temp];
20                     dict[temp] = dict[temp] + 1;
21                 }
22                 else
23                 {
24                     dict.Add(temp, 1);
25                 }
26                 
27             }
28 
29             return result;
30         }
31 }

  第15行,處理一下負數的情況,將其轉為對應的%操作取得的正整數。

 

560. 和為K的子數組

給定一個整數數組和一個整數 k,你需要找到該數組中和為 k 的連續的子數組的個數。

示例 1 :

輸入:nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 為兩種不同的情況。
說明 :

數組的長度為 [1, 20,000]。
數組中元素的範圍是 [-1000, 1000] ,且整數 k 的範圍是 [-1e7, 1e7]。

 

  這道題目的思路也是一樣,但我還是把它記錄了下來,因為覺得對比自己的思路和官方思路的過程很有意思。 解法和前面類似,我們也需要利用首碼和來求解。只不過這類是Sumy - Sumx = K。先來看看筆者沒有通過的的提交吧:

 1 public class Solution {
 2         public int SubarraySum(int[] nums, int k)
 3         {
 4             Dictionary<int, int> dict = new Dictionary<int, int>();
 5 
 6             int sum = 0;
 7 
 8             for (int i = 0; i < nums.Length; i++)
 9             {
10                 sum += nums[i];
11                 int count = 0;
12                 dict.TryGetValue(sum, out count);
13                 dict[sum] = ++count;
14             }
15 
16             int result = 0;
17 
18             foreach (var item in dict)
19             {
20                 if (item.Key == k)
21                 {
22                     result += item.Value;
23                 }
24 
25                 int temp = item.Key + k;
26 
27                 if (dict.Keys.Contains(temp))
28                 {
29                     if (temp != item.Key)
30                     {
31                         result += item.Value * dict[temp];
32                     }
33                     else
34                     {
35                         result += (dict[temp] - 1) * (dict[temp] - 1);
36                     }
37                     
38                 }
39                 
40             }
41 
42             return result;
43         }
44 }

  上面的代碼其實已經通過了大多數的測試用例,但在第56個用例失敗了。

  case 56很簡單,輸入是[-1,-1,1] ,1。如果按照我的思路,那麼儲存首碼和的Dict中的結果應該是(-1,2),(-2,1)。即首碼和是-1的情況出現了兩次,首碼和是-2的情況出現了一次。此時我們要求的結果K=1, 因此對於首碼和是-2的這種情況,如果我們可以找到首碼和是-1的首碼是不是就滿足了呢?我一開始是這麼想的,然鵝被現實打臉 ( ̄ε(# ̄) 了。其實題目中滿足要求的只有[1] 這種情況。

  再仔細思考,其實我遇到的問題是既需要利用Hash來實現O(1)的訪問,又需要知道順序,來過濾到不可能的情況。

  再來看看官方的解法吧:

 1 public class Solution {
 2         public int SubarraySum(int[] nums, int k)
 3         {
 4             Dictionary<int, int> dict = new Dictionary<int, int>();
 5 
 6             int sum = 0;
 7             int result = 0;
 8 
 9             for (int i = 0; i < nums.Length; i++)
10             {
11                 sum += nums[i];
12 
13                 int cha = sum - k;
14 
15                 if (cha == 0)
16                     result++;
17 
18                 if (dict.Keys.Contains(cha))
19                     result += dict[cha];
20 
21                 int count = 0;
22                 dict.TryGetValue(sum, out count);
23                 dict[sum] = ++count;
24             }
25 
26             return result;
27         }
28 }

  還是想法不夠成熟,人家直接放到一次迴圈里搞定了,邊生成Hash集合,邊處理數據,同時也避免了上面提到的那種情況。試著解釋一下上面那種情況:其實是用已生成的首碼和去減去未生成的首碼和,真實情況下這是不合邏輯的,但是由於先獨立的計算了一遍首碼和掩蓋了這個問題。

  

  PS: 即使我一開始的思路沒錯,時間複雜度也是O(2n), 雖然最終可以計算為O(n)。而官方的直接就是O(n),當數據量不大時,由於常數被官方完爆。ORZ

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 第一單元 常用標準包(一) 2 3 1.學習目標 4 5 1. 掌握strings常用函數使用 6 2. 掌握strconv常用函數使用 7 3. 熟悉encoding常用函數使用 8 9 2.strings標準包 10 11 2.1 Contains 12 13 用途:字元串包含關係 14 1 ...
  • Auto.js是什麼 安卓腳本框架 可以做的事情 數據監控:可以監視當前手機的數據。 圖片監控:截圖獲取當前頁面信息。 控制項操作:模擬操作手機控制項。 自動化工作流:編寫簡單的腳本,完成一系列自動化操作。如:微信自動點贊,快速搶單等。 定時功能:定時執行某個腳本,來完成定時任務。如:定時打卡簽到等。 ...
  • 前言 在JAVA虛擬機記憶體管理中,堆、棧、方法區、常量池等概念經常被提到,對理論知識的理解也常常停留在字面意思上,比如說堆記憶體中存放對象,棧記憶體中存放局部變數,常量池中存放字元串常量表等,本篇文章通過一個有趣的例子,儘量將這些理論概念通過程式樣例及圖解的方式表達清楚,讓我們更能深入底層知識。 例子 ...
  • 前言 在ASP.NET Core中最大的更改之一是對Http請求管道的更改,在ASP.NET中我們瞭解HttpHandler和HttpModule但是到現在這些已經被替換為中間件那麼下麵我們來看一下他們的不同處。 HttpHandler Handlers處理基於擴展的特定請求,HttpHandler ...
  • 0. 前言 在上一篇,我們搭建了一個項目框架,基本上是一個完整的項目。目前而言,大部分的應用基本都是這個結構。好的,不廢話了,進入今天的議題:完成並實現數據層的基礎實現。 1. 數據實體 通常情況下,一個項目的數據實體中欄位並不是完全沒有規律可尋。通常情況下,必須有一個主鍵。有些時候,會要求在數據表 ...
  • 前言 在本章中,主要是藉機這個C#基礎篇的系列整理過去的學習筆記、歸納總結並更加理解透徹。 在.Net開發中,我們經常會遇到並使用過委托,如果能靈活的掌握並加以使用會使你在編程中游刃有餘,然後對於很多接觸C#時間不長的開發者而言,較好的理解委托和事件並不容易。 本節主要是講述對委托的定義、委托的使用 ...
  • 在打開頁面時報錯:無法使用前導 .. 在頂級目錄上退出 原因:頂級目錄不能使用../ 經過查找,發現站點地圖裡出問題了 把../去掉後正常 或者在地址前加~/(表示應用程式的根目錄) ...
  • 一、WPF介紹 WPF全稱 Windows Presentation Foundation,幹啥用的? 主要是用來製作Windows桌面客戶端軟體的。 .Net平臺下製作Windows桌面客戶端軟體主要有兩個,一個Winform,還有一個就是WPF了。 事件驅動時代:開發客戶端便採用Winform, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...