Leetcode Easy題小解(C++語言描述)1

Leetcode Easy題小解(C++語言描述)

相交鏈表

給你兩個單鏈表的頭節點 headAheadB ,請你找出并返回兩個單鏈表相交的起始節點。如果兩個鏈表不存在相交節點,返回 null

圖示兩個鏈表在節點 c1 開始相交**:**

在這里插入圖片描述

題目數據 保證 整個鏈式結構中不存在環。

注意,函數返回結果后,鏈表必須 保持其原始結構

方法一:使用unordered_set存儲元素查詢是否重復

? 有一個招數就是使用unordered_set存儲一下我們的一個鏈表的元素,然后,去用另一個鏈表遍歷查看我們的元素是否在unordered_set種已經出現過了。

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {unordered_set<ListNode*> sets;// init the sets to get the count;while(headA){sets.insert(headA);headA = headA->next; // go ahead;}while(headB){if(sets.count(headB)){// owns the count, and returns;return headB;}headB = headB->next;}return nullptr;}
};

? 這種方式最直觀,也是筆者的第一反應。

方法2:快慢指針判決

? 下面我們來看快慢指針的辦法進行求解。我們知道,假設A鏈表的長度是a,B鏈表的長度是b,公共部分設成c,那么顯然,我們快慢指針的判別法可以是這樣的:即嘗試兩個指針都走一次A,B鏈表,當走到我們的焦點的時候,我們發現:

A: 走了 a + (b - c)
B: 走了 b + (a - c)

? 我們高興的發現兩個指針走的部署相等,因此實際上,我們完全就讓快慢指針在交點處相等了。

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* curA = headA;ListNode* curB = headB;while(curA != curB){curA = (curA ? curA->next : headB); // 空了咱們去BcurB = (curB ? curB->next : headA); // 空了咱們去A}return curA;}
};

鏈表反轉

給你單鏈表的頭節點 head ,請你反轉鏈表,并返回反轉后的鏈表。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/

? 反轉鏈表比較簡單,我們實際上的難點在于,我們不能立馬修改當前遍歷節點的下一個節點,需要做緩存

class Solution {
public:ListNode* reverseList(ListNode* head) {if(!head || !head->next) return head; // stop with null and onlyListNode* current = head;ListNode* prev = nullptr;ListNode* next_one;while(current){// cached the next onenext_one = current->next;// modify the next one's next to the cur to reversecurrent->next = prev;// restore cachesprev = current;current= next_one;}return prev;}
};

? 就可以看到,我們做的實際上就是簡單的swap操作,沒啥好說的。

判斷回文鏈表

? 給你一個單鏈表的頭節點 head ,請你判斷該鏈表是否為回文鏈表。如果是,返回 true ;否則,返回 false 。

? 嘛!顯然,咱們沒法逆序遍歷鏈表,有一種偷懶的辦法兄弟們,那就是用一下棧這個特性。我們知道棧是一個經典的FILO結構,我們按照遍歷順序壓棧我們的單鏈表遍歷結果,之后我們只需要再遍歷一下鏈表,跟我們的棧進行對比

class Solution {
public:bool isPalindrome(ListNode* head) {stack<int> caches;ListNode* cached_head = head;while(head){caches.push(head->val);head = head->next;}     while(cached_head){if(cached_head->val != caches.top()){return false;}cached_head = cached_head->next;caches.pop();}return true;}
};

前K系列:找出前K個高頻元素

? 給你一個整數數組 nums 和一個整數 k ,請你返回其中出現頻率前 k 高的元素。你可以按 任意順序 返回答案。

? 其實回答很簡單,那就是第一步是統計我們的元素個數,我們可以使用的是unordered_map來做這個事情,其鍵值對我們采用的是:{元素,個數}鍵值對。之后咱們做的事情就是塞到大根堆進行默認的排序。需要注意的是,咱們的大根堆對pair的排序看的是第一個數大不大,所以咱們往隊列里push我們的東西的時候,是需要我們調換一下鍵值對的順序的。

class Solution {
public:vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int, int> counters; // <nums, count>for(const auto& num : nums){counters[num]++;}// next, we shell check and reordered as prioirty queuepriority_queue<pair<int, int>> pq;for(const auto& each : counters){pq.push({each.second, each.first});}vector<int> result;for(int i = 0; i < k; i++){result.emplace_back(pq.top().second);pq.pop();}return result;}
};

? 可以看到我們的priority_queue自動幫助我們處理排序的事情了。如果是小K個,那么我們只需要換greater<int>就好了

第K系列:使用O(N)復雜度尋找第K個大小的數字

可以用sort等嘛?

? 不能,因為std::sort是完全快排,實際上復雜度是O(NlogN),我們需要改進成快速選擇的方式進行改進

class Solution {
public:int partition(vector<int>& nums, int left, int right){int pivot = nums[right];int i = left;for(int j = left; j < right; j++){if(nums[j] <= pivot){swap(nums[i], nums[j]);i++;}}swap(nums[i], nums[right]);return i; // return new pivot}int quick_selection(vector<int>& n, int left, int right, int k_smallest){if (left == right) return n[left];int pivot = partition(n, left, right);if(pivot == k_smallest){return n[pivot];}else if (pivot < k_smallest){// leftreturn quick_selection(n, pivot + 1, right, k_smallest);}else{return quick_selection(n, left, pivot - 1, k_smallest);}}int findKthLargest(vector<int>& nums, int k) {int n = nums.size();int target = n - k; // 第 k 大 → 第 n - k 小return quick_selection(nums, 0, n - 1, target);}
};

1. findKthLargest 函數:“化大為小,找對目標”

想象你有一堆撲克牌,現在讓你找出第 3 大的那張牌。

int findKthLargest(vector<int>& nums, int k) {int n = nums.size();// 關鍵一步:把“找第k大”轉換成“找第(n-k)小”int target = n - k; // 例如,有5張牌,找第1大(最大的),就是找第5-1=4小的(也就是索引為4的,如果從0開始數)// 找第3大,就是找第5-3=2小的(也就是索引為2的)return quick_selection(nums, 0, n - 1, target);
}
  • 它的任務: 你告訴我,你想要這堆牌里第幾大的牌。
  • 它的聰明之處: 它會偷偷地把你的要求“翻譯”一下。比如,如果你說要找第 3 大的牌,它會心想:“哦,這不就是說,在所有牌都排好序之后,從最小的開始數,第 (N?3) 張牌嗎?”(N 是總牌數)。
  • 委托任務: 翻譯完之后,它就把這個“找第 N?k 小的牌”的任務,交給下一級的專家 quick_selection 去辦了。

2. partition 函數:“分堆、找個好位置”

這個函數是整個算法的“幕后功臣”,它每次的作用是:隨機挑一個“參考牌”,然后把其他牌根據這個參考牌分成兩堆。

int partition(vector<int>& nums, int left, int right)
{int pivot = nums[right]; // 選定最右邊的牌作為“參考牌”(基準值)int i = left;            // i 指針:表示“比參考牌小的牌”的區域的右邊界// j 指針從左邊開始遍歷,但不到right(因為right是參考牌)for(int j = left; j < right; j++){if(nums[j] <= pivot){ // 如果當前牌(nums[j])比“參考牌”小或者相等swap(nums[i], nums[j]); // 就把這張牌挪到“比參考牌小的區域”里去i++;                     // “比參考牌小的區域”的邊界就往右擴大一格}}// 循環結束后,i 指向的位置,就是所有“比參考牌小的牌”后面緊跟著的位置// 也就是說,i左邊的牌都 <= pivot,i右邊的牌都 > pivot (暫時)swap(nums[i], nums[right]); // 把“參考牌”(nums[right])放到 i 指向的位置// 這樣,i位置的牌就是新的參考牌,它左邊的都比它小,右邊的都比它大return i; // 返回這個“參考牌”最終所在的位置(索引)
}
  • 它的任務: 拿到一堆牌(一個子數組),然后重新整理一下這堆牌。

  • 怎么整理:

    1. 它先從這堆牌的最右邊挑一張牌,把它作為**“參考牌” (pivot)**。
    2. 它有一個**“小牌區”的邊界 i**,最開始在最左邊。
    3. 然后它從最左邊開始,一張一張地看牌 (j 遍歷):
      • 如果它看的這張牌比“參考牌”小(或者一樣大),那么這張牌就應該放在“小牌區”里。它就會把這張牌和“小牌區”邊界 i 上的牌交換一下位置。然后,“小牌區”的邊界 i 就往右移一位。
      • 如果它看的這張牌比“參考牌”大,它就不管,繼續看下一張。
    4. 當所有牌都看完了(j 走到了 right - 1),這時候,從起始位置到 i-1 的所有牌都比“參考牌”小或相等。i 指向的牌和 i 右邊的牌都比“參考牌”大(或者還沒有處理的牌)。
    5. 最后,它會把最開始選定的那張**“參考牌”**(原來在 right 位置)放到 i 所指的位置上。
  • 結果: partition 函數執行完后,數組就變成這樣:

    [小于等于參考牌的牌 | 參考牌本身 | 大于參考牌的牌]

    而且,返回的 i 就是這個**“參考牌”最終所在的位置**。這個位置非常重要,因為它告訴我們“參考牌”在整個排序好之后,會處于哪個確切的索引。


3. quick_selection 函數:“縮小范圍,直到找到”

這是遞歸尋找目標牌的主管。

int quick_selection(vector<int>& n, int left, int right, int k_smallest){if (left == right) return n[left]; // 如果只剩一張牌了,那這張牌就是答案,直接返回int pivot_index = partition(n, left, right); // 調用 partition,找到“參考牌”的新位置if(pivot_index == k_smallest){// 情況1:運氣真好!“參考牌”的位置正好就是我們要找的第k_smallest小牌的位置!return n[pivot_index]; // 找到了,直接返回這張牌}else if (pivot_index < k_smallest){// 情況2:“參考牌”的位置比我們想找的牌的位置靠左了// 說明我們想找的牌在“參考牌”的右邊那堆牌里return quick_selection(n, pivot_index + 1, right, k_smallest); // 遞歸去右邊那堆牌里找}else{// 情況3:“參考牌”的位置比我們想找的牌的位置靠右了// 說明我們想找的牌在“參考牌”的左邊那堆牌里return quick_selection(n, left, pivot_index - 1, k_smallest); // 遞歸去左邊那堆牌里找}
}
  • 它的任務: 在指定的牌堆范圍 (leftright) 里,找到“翻譯”后的那個 k_smallest 索引的牌。
  • 怎么找:
    1. 基地情況: 如果這堆牌里只剩下一張牌了(left == right),那這張牌肯定就是我們要找的,直接拿走。
    2. 分區: 否則,它會調用 partition 函數,把當前這堆牌重新分一下,得到一個**“參考牌”的新位置 pivot_index**。
    3. 判斷:
      • 正好找到! 如果這個 pivot_index 恰好就是我們要找的 k_smallest 索引,那太好了!pivot_index 上的那張牌就是答案,直接返回!
      • 找錯了,往右邊找! 如果 pivot_indexk_smallest 小,說明“參考牌”排得太靠左了,我們要找的牌肯定在它的右邊那堆牌里。所以,它會pivot_index + 1right 的范圍里,繼續用同樣的方法找 k_smallest 索引的牌。
      • 找錯了,往左邊找! 如果 pivot_indexk_smallest 大,說明“參考牌”排得太靠右了,我們要找的牌肯定在它的左邊那堆牌里。所以,它會leftpivot_index - 1 的范圍里,繼續用同樣的方法找 k_smallest 索引的牌。

這個算法的核心思想就是:

  1. 我有一堆亂序的牌。
  2. 我想找到第 N?k 小的那張牌。
  3. 我隨機(這里是選最右邊)挑一張牌作為“參考牌”。
  4. 我把所有比“參考牌”小的牌挪到它左邊,所有比它大的牌挪到它右邊。然后把“參考牌”放到它最終該去的位置。
  5. 現在“參考牌”的位置確定了。
  6. 我就看這個“參考牌”的位置是不是我想要的那個第 N?k 小的索引。
    • 如果是,那我就找到了!
    • 如果不是,我就只去“參考牌”的左邊那堆牌或者右邊那堆牌里繼續找(因為我知道我要的牌肯定在那一堆里),另一堆牌就完全不用管了。
  7. 這樣,每次都能排除掉一部分不需要查找的牌,大大提高了效率。

它和快速排序最大的不同是,快速排序要排序兩邊,而快速選擇只排序包含目標元素的那一邊,所以平均情況下比完全排序要快得多。

**

  1. 我有一堆亂序的牌。
  2. 我想找到第 N?k 小的那張牌。
  3. 我隨機(這里是選最右邊)挑一張牌作為“參考牌”。
  4. 我把所有比“參考牌”小的牌挪到它左邊,所有比它大的牌挪到它右邊。然后把“參考牌”放到它最終該去的位置。
  5. 現在“參考牌”的位置確定了。
  6. 我就看這個“參考牌”的位置是不是我想要的那個第 N?k 小的索引。
    • 如果是,那我就找到了!
    • 如果不是,我就只去“參考牌”的左邊那堆牌或者右邊那堆牌里繼續找(因為我知道我要的牌肯定在那一堆里),另一堆牌就完全不用管了。
  7. 這樣,每次都能排除掉一部分不需要查找的牌,大大提高了效率。

它和快速排序最大的不同是,快速排序要排序兩邊,而快速選擇只排序包含目標元素的那一邊,所以平均情況下比完全排序要快得多。

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

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

相關文章

EP01:【NLP 第二彈】自然語言處理概述

一、NLP通向智能之路 1.1 圖靈測試 1.1.1 提出背景 由計算機科學家阿蘭?圖靈于 1950 年提出&#xff0c;是早期衡量機器智能水平的重要概念。 1.1.2 提出目的 判斷機器是否能表現出與人類相當的智能行為。 1.1.3 測試原理 場景設定&#xff1a;測試中存在一位人類測試者&#…

Ansible 查看PostgreSQL的版本

Ansible的基礎知識就不說了直接貼劇本- name: Check PostgreSQL versionhosts: db_serversbecome: yesvars:ansible_python_interpreter: /usr/bin/python3db_name: postgresdb_user: postgresdb_password: your_passwordtasks:- name: Install psycopg2ansible.builtin.packag…

【視覺SLAM筆記】第9章 后端1

一、理論1. 狀態估計的概率解釋我們來深入探討一下視覺SLAM中狀態估計的概率解釋。這可以說是理解現代SLAM算法&#xff08;尤其是后端優化&#xff09;的基石1. 問題的核心&#xff1a;不確定性SLAM&#xff08;同步定位與建圖&#xff09;的本質是在一個未知環境中&#xff0…

(數據結構)復雜度

基本概念說明 數據結構 定義&#xff1a;數據結構(Data Structure)是計算機存儲、組織數據的方式&#xff0c;指相互之間存在?種或多種特定關系的數據元素的集合。沒有?種單?的數據結構對所有用途都有用&#xff08;要考慮適配、效率問題&#xff0c;在不同情況下使用合適的…

玩轉Docker | 使用Docker部署bender個人導航頁工具

玩轉Docker | 使用Docker部署bender個人導航頁工具 前言 一、bender介紹 Bender 簡介 Bender 的主要特點 二、系統要求 環境要求 環境檢查 Docker版本檢查 檢查操作系統版本 三、部署bender服務 下載bender鏡像 編輯部署文件 創建容器 檢查容器狀態 檢查服務端口 安全設置 四、…

解決了困擾我的upload靶場無法解析phtml等后綴的問題

本文章為解決困擾我的 upload 靶場無法解析 phtml 問題 ? 這個問題直接讓我過不了Upload-Pass-03這一關&#xff0c;一直卡著。 ? 痛太痛了 &#xff0c;為什么無法解析上傳之后的 phtml 后綴文件&#xff01;這塊兒折磨了博主一天多&#xff0c;太不容易了&#xff0c;查找…

Leetcode百題斬-二分搜索

二分搜索也是一個很有趣的專題&#xff0c;被做過的題中&#xff0c;剛好一個Easy&#xff0c;一個Medium和一個Hard&#xff0c;剛好可以看看&#xff0c;二分搜索的三個難度等級都是啥樣的。 124. Binary Tree Maximum Path Sum[Hard]&#xff08;詳見二叉樹專題&#xff09;…

【IDEA】格式化代碼工具配置

格式化代碼快捷鍵&#xff1a; CtrlAltL格式代碼的時候不會再方法名與參數中間添加空格默認不勾選的情況下&#xff1a;代碼樣例&#xff1a;勾選之后的樣例&#xff1a;選擇不勾選&#xff0c;IDEA默認情況下就是不勾選的狀態忽略加載文件有些非必要加載到開發工具中的文件我們…

驅動開發(3)|rk356x驅動GPIO基礎應用之點亮led燈

點亮LED燈看似是一個基礎的操作&#xff0c;但實際上&#xff0c;許多高級應用也依賴于高低電平的切換。例如&#xff0c;脈沖寬度調制&#xff08;PWM&#xff09;信號可以用來精確控制電機的轉速&#xff0c;通過改變脈沖的頻率和占空比&#xff0c;實現對電機的精確調節&…

手動搭建PHP環境:步步為營,解鎖Web開發

目錄一、引言二、準備工作2.1 明確所需軟件2.2 下載軟件三、Windows 系統搭建步驟3.1 安裝 Apache 服務器3.2 安裝 PHP3.3 集成 Apache 與 PHP3.4 安裝 MySQL3.5 配置 PHP 連接 MySQL四、Linux 系統搭建步驟&#xff08;以 Ubuntu 為例&#xff09;4.1 更新系統4.2 安裝 Apache…

DrissionPage:一款讓網頁自動化更簡單的 Python 庫

在網頁自動化領域&#xff0c;Selenium 和 Playwright 早已是開發者耳熟能詳的工具。但今天要給大家介紹一款更輕量、更易用的 Python 庫 ——DrissionPage。它以 "融合 selenium 和 requests 優勢" 為核心設計理念&#xff0c;既能像 requests 一樣高效處理靜態網頁…

理解Grafana中`X-Scope-OrgID`的作用與配置

X-Scope-OrgID的作用 該HTTP Header用于標識Loki日志數據的所屬租戶&#xff08;組織&#xff09;。在多租戶模式下&#xff0c;Loki通過此Header隔離不同團隊或用戶的數據&#xff0c;確保查詢和存儲的獨立性。數據隔離&#xff1a; 租戶A的日志標記為X-Scope-OrgID: team-a&a…

【PycharmPyqt designer桌面程序設計】

在 main.py 中調用 Qt Designer 生成的 windows.py&#xff08;假設它是 PySide2 版&#xff09;。 只要把兩個文件放在同一目錄即可直接運行。 ──────────────────── 1?? windows.py&#xff08;Qt Designer 生成&#xff0c;已轉碼&#xff09; # -*-…

Unity Android Logcat插件 輸出日志中文亂碼解決

背景之前安卓真機調試看日志&#xff0c;一直用的是Android Studio自帶的adb命令進行看日志&#xff0c;不太方便&#xff0c;改用Unity自帶的安卓日志插件時&#xff0c;存在中文日志亂碼問題。插件安裝基于Unity6000.1.11版本&#xff1a;Window -> Package Management -&…

Halcon雙相機單標定板標定實現拼圖

1.Halcon圖像拼接算法在之前的文章里也寫過&#xff0c;主要是硬拼接和特征點拼接兩種方式&#xff0c;今天增加另一種拼接圖像的方式。應用場景是多個相機聯合一起拍大尺寸的物體&#xff0c;并且相機視野之間存在重疊區域。通過在同一個標定板上面標定&#xff0c;計算兩個相…

動物世界一語乾坤韻芳華 人工智能應用大學畢業論文 -仙界AI——仙盟創夢IDE

提示詞在一個奇幻的童話森林里&#xff0c;所有的動物都像人類一樣直立行走&#xff0c;穿著各種搞怪的衣服。 一只戴著超大眼鏡、穿著背帶褲的烏龜&#xff0c;正一本正經地站在一個蘑菇舞臺上&#xff0c;拿著一根樹枝當作麥克風&#xff0c;準備唱歌。它的眼鏡總是往下滑&am…

SpringBoot(原理篇)

大家好&#xff0c;這里是 盛碼筆記。 本篇我們來聊一聊 Spring Boot 的“魔法”是如何實現的。你可能已經用過 Spring Boot 快速搭建項目&#xff0c;但有沒有想過&#xff1a;為什么只需要引入幾個 starter&#xff0c;Spring Boot 就能自動配置好整個應用環境&#xff1f; …

數據結構:棧(區間問題)

碼蹄集OJ-小碼哥的棧 #include<bits/stdc.h> using namespace std; #define int long long const int N1e67; struct MOOE {int ll,rr; }; stack<MOOE>st; signed main( ) {ios::sync_with_stdio(false);cin.tie(nullptr);int n;cin>>n;while(n--){int opt…

Vue 中 data、watch、created 和 methods

以下是 Vue 中 data、watch、created 和 methods 的詳細解釋&#xff0c;結合常見使用場景和示例&#xff1a;1. data&#xff1a;響應式數據容器 作用&#xff1a;定義組件的響應式數據&#xff08;狀態&#xff09;&#xff0c;當數據變化時&#xff0c;視圖自動更新。特點&a…

精密模具冷卻孔內輪廓檢測方法探究 —— 激光頻率梳 3D 輪廓檢測

引言精密模具冷卻孔的內輪廓精度直接影響注塑成型效率與制品質量。冷卻孔具有深徑比大&#xff08;可達 25:1&#xff09;、結構復雜&#xff08;多為螺旋形或異形&#xff09;、表面質量要求高&#xff08;Ra≤0.2μm&#xff09;等特點&#xff0c;傳統檢測方法難以滿足其高精…