【哈希表與字符串的算法之路:思路與實現】—— LeetCode

文章目錄

  • 兩數之和
  • 面試題01.02.判定是否為字符重排
  • 存在重復元素
  • 存在重復元素||
  • 字母異位詞分組
  • 最長公共前綴和
  • 最長回文子串
  • 二進制求和
  • 字符串相乘

兩數之和

在這里插入圖片描述
這題的思路很簡單,在讀完題目之后,便可以想到暴力枚舉,直接遍歷整個數組兩遍即可,但是時間復雜度高,下面是運行之后的結果
在這里插入圖片描述

很簡單快速的將這個題目寫完了,但是有沒有更高效,時間復雜度更低的方法呢?
當然!
思路:

  • 利用哈希表進行優化已經知道了target,那么遍歷讓x = target-nums[i]如果x在哈希表中存在,那么就存在這組元素——即結果。
class Solution 
{
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> hash;for(int i = 0; i < nums.size(); i++){int x = target - nums[i];if(hash.count(x)) return {hash[x], i};hash[nums[i]] = i;}return {};}
};

面試題01.02.判定是否為字符重排

在這里插入圖片描述
這個題目也是一個很經典的題目,也是一個一眼題

  • 方法一:直接將兩個字符串進行排序,相同就是true,不同就是false。時間復雜度也是最優的
class Solution 
{
public:bool CheckPermutation(string s1, string s2){sort(s1.begin(),s1.end());sort(s2.begin(),s2.end());if(s1 == s2) return true;else return false;}
};
  • 方法二:可以用一個數組替代哈希表,將遍歷一組字符串進入哈希表,然后再遍歷另外一組字符串——從哈希表中依次減少另外一組字符串的個數,最后結果為0便是true,否則剩余數字就是false。
class Solution 
{
public:bool CheckPermutation(string s1, string s2) {if(s1.size() != s2.size()) return false;int hash[26] = { 0 };//先統計第一個字符串的信息for(auto ch : s1)hash[ch - 'a']++;//掃描第二個字符串,看看能不能重排for(auto ch : s2){hash[ch - 'a']--;if(hash[ch - 'a'] < 0) return false;}        return true;}
};

存在重復元素

在這里插入圖片描述

  • 思路:
    將數組一遍遍歷,一邊插入到哈希表當中,如果遍歷到每個元素的時候已經存在該元素,直接返回true即可,如果遍歷完之后沒有元素了返回false。
class Solution 
{
public:bool containsDuplicate(vector<int>& nums) {// 創建一個無序集合,用于存儲nums向量中的唯一元素unordered_set <int> hash;// 遍歷nums向量中的每個元素for(auto x : nums){// 如果元素已經在集合中,說明存在重復元素if(hash.count(x)) return true;  // 如果發現重復元素,返回trueelse hash.insert(x);  // 如果沒有重復元素,將該元素插入集合中}// 如果遍歷完后沒有發現任何重復元素,返回falsereturn false;}
};

存在重復元素||

在這里插入圖片描述

  • 思路: 這題跟上面一題基本一樣只不過增加了一個| i - j | <= k的條件。
class Solution 
{
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {// 創建一個哈希表,用于存儲每個元素及其最后出現的位置unordered_map<int, int> hash;// 遍歷nums向量中的每個元素for(int i = 0; i < nums.size(); i++){// 如果當前元素在哈希表中已經存在if(hash.count(nums[i])){// 判斷當前索引與該元素上次出現索引的差是否小于等于kif(i - hash[nums[i]] <= k) return true;  // 如果差值小于等于k,返回true,表示找到滿足條件的重復元素}// 更新當前元素在哈希表中的位置hash[nums[i]] = i;}// 如果遍歷完所有元素都沒有找到滿足條件的重復元素,返回falsereturn false;}
};

字母異位詞分組

在這里插入圖片描述

  • 思路:
  1. 排序法:
    對于每個字符串,將其按字母排序。排序后的字符串可以作為它們的“標識符”,即所有字母異位詞排序后得到的字符串是相同的。
    例如,“eat”和“tea”排序后都會變成“aet”,這使得我們能夠將它們歸為一組。

  2. 使用哈希表分組:
    使用一個哈希表 unordered_map<string, vector>,其中鍵是排序后的字符串,值是具有相同排序后的字母異位詞的字符串集合。
    對于每個字符串,排序并將它放入對應的組中。如果該組已經存在,就將其添加到對應組里;如果該組不存在,就創建新組。

  3. 提取結果:
    最后,從哈希表中提取出所有的字母異位詞組并返回。

class Solution 
{
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 創建一個哈希表,key是排序后的字符串,value是與該排序字符串對應的字母異位詞列表unordered_map <string, vector<string>> hash;// 1. 將所有字符串排序并分組for(auto& s : strs){// 將字符串復制到tmp中,然后排序string tmp = s;sort(tmp.begin(), tmp.end());// 根據排序后的字符串,將原始字符串加入哈希表的對應組中hash[tmp].push_back(s);}// 2. 從哈希表中提取出結果vector<vector<string>> ret;for(auto&[x, y] : hash){// 將每一組字母異位詞加入到結果列表中ret.push_back(y);}// 返回結果return ret;}
};

最長公共前綴和

在這里插入圖片描述

  • 思路:
    這道題的思路是通過逐個字符地檢查所有字符串的字符來找出最長公共前綴。從第一個字符串的第一個字符開始,逐個比較該位置上其他字符串的字符是否相同。如果遇到不同的字符或某個字符串的長度不足,就返回當前找到的公共前綴。如果沒有遇到不匹配的字符,說明第一個字符串本身就是所有字符串的公共前綴,直接返回它——中心擴展算法
class Solution 
{
public:string longestCommonPrefix(vector<string>& strs) {// 遍歷第一個字符串的每一個字符for(int i = 0; i < strs[0].size(); i++){// 獲取當前字符char tmp = strs[0][i];// 遍歷后續的字符串,檢查是否在當前字符位置上與第一個字符串相同for(int j = 1; j < strs.size(); j++){// 如果某個字符串的長度小于等于i,或者字符不匹配,返回從0到i的子串作為公共前綴if(i == strs[j].size() || tmp != strs[j][i])return strs[0].substr(0, i);}}// 如果沒有遇到不匹配的情況,說明第一個字符串就是公共前綴return strs[0];}
};

最長回文子串

  • 思路:
    這道題要求找到一個字符串中最長的回文子串。回文串是指從前往后和從后往前讀都相同的字符串。我們可以通過 中心擴展法 來解決這個問題。每個回文子串都有一個中心,中心可以是一個字符(對于奇數長度回文串)或者兩個字符之間(對于偶數長度回文串)。從每個字符(或字符間隙)向外擴展,檢查左右兩邊的字符是否相等,直到不再相等為止。
class Solution 
{
public:string longestPalindrome(string s) {// 獲取字符串長度nint n = s.size(), begin = 0, len = 0;// 遍歷每個字符,嘗試找到以該字符為中心的回文串for(int i = 0; i < n; i++){// 處理奇數長度回文串,以字符s[i]為中心int right = i, left = i;// 擴展左右兩邊,直到不滿足回文條件while(left >= 0 && right < n && s[left] == s[right]){left--;right++;}// 更新最長回文串的起始位置和長度if(right - left - 1 > len){begin = left + 1;len = right - left - 1;}// 處理偶數長度回文串,以字符s[i]和s[i+1]為中心right = i + 1, left = i;while(left >= 0 && right < n && s[left] == s[right]){left--;right++;}// 更新最長回文串的起始位置和長度if(right - left - 1 > len){begin = left + 1;len = right - left - 1;}}// 返回最長回文子串return s.substr(begin, len);}
};

二進制求和

在這里插入圖片描述

  • 思路:
    我們從 a 和 b 的末尾(即最低位)開始逐位進行加法運算,類似于手動加法的過程。每一位相加時,判斷是否需要進位。進位的處理通過變量 t 來存儲,當兩位數字加起來大于或等于2時,t 就會向下一位傳遞進位。最終,逐位的結果被累積到字符串 ret 中,并且需要反轉,因為我們從低位到高位計算。整個過程確保處理了兩者的不同長度以及最終的進位。
class Solution 
{
public:string addBinary(string a, string b) {string ret; // 用于存儲結果的字符串int cur1 = a.size() - 1, cur2 = b.size() - 1, t = 0; // cur1, cur2分別是a和b的當前字符索引,t是進位// 遍歷兩個字符串直到都遍歷完并且沒有進位while(cur1 >= 0 || cur2 >= 0 || t){// 如果a還有剩余位,取出a對應位置的數字并加到t中if(cur1 >= 0) t += a[cur1--] - '0';  // 如果b還有剩余位,取出b對應位置的數字并加到t中if(cur2 >= 0) t += b[cur2--] - '0';  // 將當前位的結果加到結果字符串中,t % 2是當前位(0或1),進位需要除以2ret += t % 2 + '0';t /= 2; // 更新進位,t // 2}// 由于我們是從低位到高位處理的,最后需要反轉結果字符串reverse(ret.begin(), ret.end());return ret; // 返回加法結果的二進制字符串}
};

字符串相乘

在這里插入圖片描述

  • 思路:
    這道題目要求實現兩個大整數的乘法。我們不能直接將兩個大整數轉換為整數進行計算,因為它們的長度可能超出整數類型的表示范圍。我們通過模擬豎式乘法的方法來手動計算乘積。首先,我們逆序遍歷兩個字符串,將每一位的數字相乘并加到臨時結果數組中,處理乘法的每一位。然后,我們處理進位,最后將結果反轉并處理前導零,得到最終的乘積結果。
    在這里插入圖片描述
    在這里插入圖片描述
class Solution 
{
public:string multiply(string num1, string num2){// 獲取兩個字符串的長度int m = num1.size(), n = num2.size();// 反轉字符串,以便從低位開始計算reverse(num1.begin(), num1.end());reverse(num2.begin(), num2.end());// 臨時數組用于存儲每一位的乘積結果vector<int> tmp(m + n - 1);// 進行無進位的相乘for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');// 處理進位int cur = 0, t = 0;string ret;while(cur < m + n - 1 || t != 0){// 將當前的乘積加到結果中if(cur < m + n - 1) t += tmp[cur++];// 取當前位的數字,并更新進位ret += t % 10 + '0';t /= 10;}// 處理前導零while(ret.size() > 1 && ret.back() == '0') ret.pop_back();// 反轉最終的結果字符串reverse(ret.begin(), ret.end());return ret;  // 返回最終的乘積結果}
};

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

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

相關文章

RabbitMQ入門:從安裝到高級消息模式

文章目錄 一. RabbitMQ概述1.1 同步/異步1.1.1 同步調用1.1.2 異步調用 1.2 消息中間件1.2.1 概念1.2.2 作用1.2.3 常見的消息中間件1.2.4 其他中間件 1.3 RabbitMQ1.3.1 簡介1.3.2 特點1.3.3 方式1.3.4 架構1.3.5 運行流程 二. 安裝2.1 Docker 安裝 RabbitMQ 三. 簡單隊列&…

kernel與modules解耦

一、耦合&#xff1a; linux的kernel與modules存在耦合版本匹配&#xff0c;在版本不匹配&#xff08;內核重新編譯后&#xff0c;或者驅動模塊編譯依賴的內核版本跟運行版本不匹配&#xff09;時候&#xff0c;會存在insmod 驅動模塊失敗的情形&#xff1b; 二、解耦&#xff…

物理約束神經網絡(PINN)和有限元方法哪個更接近“真正的物理規律”?還是兩者只是不同的數學表達?

物理約束神經網絡(Physics-Informed Neural Networks, PINN)和有限元方法(Finite Element Method, FEM)是兩種在科學計算和工程模擬中廣泛應用的數值方法。PINN 依賴深度學習來近似微分方程的解,并在訓練過程中將物理約束作為損失項融入網絡,而 FEM 通過將連續介質的物理…

UI程序的std::cout重定向輸出到Visual Studio的debug輸出窗口

常用代碼。 UI程序的std::cout重定向輸出到Visual Studio的debug輸出窗口 #include <iostream> #include <streambuf> #include <vector> #include <string> #include <afxwin.h> //MFC// 自定義 streambuf 類&#xff0c;用于重定向輸出到 Vis…

Python開發合并多個PDF文件

前言 在我們的工作中&#xff0c;可能有以下場景需要用到合并多個PDF&#xff1a; 文檔歸檔&#xff1a;在企業或組織中&#xff0c;常常需要將相關的文檔&#xff08;如合同、報告、發票等&#xff09;合并為一個PDF文件&#xff0c;以便于歸檔和管理。 報告生成&#xff1a;在…

DeepSeek 助力 C++ 開發:探索智能編程新境界

這篇文章就會詳細講講 DeepSeek 在 C 開發里到底能怎么用&#xff0c;從上面說的寫代碼、找錯誤、優化性能&#xff0c;到管理項目這些方面&#xff0c;還會給出好多實際的代碼例子&#xff0c;講講實際用起來是啥情況。目的就是給那些做 C 開發的人&#xff0c;一份全面又詳細…

C#-使用VisualStudio編譯C#工程

一.創建csproj文件 二.創建源cs文件 三.生成解決方案 四.運行解決方案 五.VisualStudio功能列表 <1.代碼格式化: CtrlKD完成代碼整體格式化 <2.窗口布局 窗口->重置窗口布局 <3.引用查找&關聯 <4.包管理 <5.日志輸出級別 工具->選項->項目解決方案…

Kafka相關的面試題

以下是150道Kafka相關的面試題及簡潔回答&#xff1a; Kafka基礎概念 1. 什么是Kafka&#xff1f; Kafka是一個分布式、可擴展、容錯的發布-訂閱消息系統&#xff0c;最初由LinkedIn開發&#xff0c;現為Apache項目。它適用于高吞吐量的場景&#xff0c;如大數據處理和實時數據…

CTF--Web安全--SQL注入之報錯注入

CTF–Web安全–SQL注入之報錯注入 一、報錯注入的概念 用戶使用數據庫查詢語句&#xff0c;向數據庫發送錯誤指令&#xff0c;數據庫返回報錯信息&#xff0c;報錯信息中參雜著我們想要獲取的隱私數據。通常在我們在頁面顯示中找不到回顯位的時候&#xff0c;使用報錯注入。 二…

深度學習中學習率調整策略

學習率衰減策略是深度學習優化過程中的一個關鍵因素&#xff0c;它決定了訓練過程中學習率的調整方式&#xff0c;從而影響模型收斂的速度和效果。不同的衰減策略在不同的任務和模型上可能有不同的表現&#xff0c;下面從我用到過的幾個衰減策略進行記錄&#xff0c;后續慢慢跟…

JavaCV

調用攝像頭 public class Camera {public static void main(String[] args) throws FrameGrabber.Exception {// 開啟抓取器OpenCVFrameGrabber grabber new OpenCVFrameGrabber(0);grabber.start();// 開啟窗口CanvasFrame canvasFrame new CanvasFrame("OpenCV Frame…

凝思linux修改mac地址

臨時性修改 /sbin/ifconfig eth0 hw ether 00:0C:29:36:97:20

前端UI編程基礎知識:基礎三要素(結構→表現→行為)

以下是重新梳理的前端UI編程基礎知識體系&#xff0c;結合最新技術趨勢與實戰要點&#xff0c;以更適合快速掌握的邏輯結構呈現&#xff1a; 一、基礎三要素&#xff08;結構→表現→行為&#xff09; 1. HTML5 核心能力 ? 語義化標簽&#xff1a;<header>, <nav&g…

面試題:實現學生管理系統

這是我在以前面試中遇到的一個問題&#xff0c; 面試官說&#xff1a;你能現場實現一個學生管理系統嗎&#xff0c;實現對學生的增刪查改這4個功能 當時寫了半天沒寫出來.....&#xff0c;所以我在這里記錄一下 10分鐘實現學生管理系統并實現 增刪查改 功能 #include <iostr…

大語言模型基礎—語言模型的發展歷程--task1

目錄 1.語言模型的發展歷程 1.1 統計語言模型 1.2 神經語言模型 1.3 預訓練語言模型 1.4 大語言模型 1.5 總結 1.6 各階段對比與演進邏輯 1.語言模型的發展歷程 語言模型的發展歷程經歷了四個主要階段&#xff1a;統計語言模型、神經語言模型、預訓練語言模型和大語言模…

BIG_EVENT

環境準備: 開發: 跨域問題: 只有瀏覽器才存在跨域問題, 此時瀏覽器的地址和前端服務一致,所以不存在跨域問題, 但是當瀏覽器中的js代碼需要向8080發送請求時就會由于存在跨域問題而失敗. 簡單的說前端和瀏覽器的地址端口是一致的,瀏覽器只能向前端服務發送請求, 所以可以使用配…

DAY33 貪心算法Ⅱ

122. 買賣股票的最佳時機 II - 力扣&#xff08;LeetCode&#xff09; 想到把整體利潤分解為每天的利潤&#xff0c;就豁然開朗了。 class Solution { public:int maxProfit(vector<int>& prices) {int result0;for(int i1;i<prices.size();i){resultmax(0,pric…

【Qt】qApp簡單介紹

1. 介紹 在Qt中&#xff0c;qApp是一個全局指針&#xff0c;它指向當前的QApplication或QGuiApplication對象。這個全局指針在Qt應用程序中非常有用&#xff0c;因為它可以讓你在任何地方訪問到應用程序對象。 在C中&#xff0c;全局指針是一個可以在程序的任何地方訪問的指針…

Redis 設置密碼無效問題解決

一、驗證密碼有沒有生效 運行cmd&#xff0c;cd到redis的目錄下 輸入“redis-cli.exe” 回車 輸入“auth 123456” 回車 若錯誤&#xff0c;說明沒有設置密碼或者設置的密碼沒有生效 輸入“exit” 回車就立即退出redis 二、解決方案是&#xff1a;直接修改后綴是 .conf 的…

手寫一些常見算法

手寫一些常見算法 快速排序歸并排序Dijkstra自定義排序交替打印0和1冒泡排序插入排序堆排序 快速排序 public class Main {public static void main(String[] args) {int nums[] {1,3,2,5,4,6,8,7,9};quickSort(nums,0,nums.length - 1);}private static void quickSort(int[…