Leetcode第284場周賽

緒論

最近發現Leetcode每周的周賽難度挺適合我的,而且時間也比較友好(不像Codeforces每次都是半夜)。所以連續參加了三周的周賽。這次才想起來應該記錄一下自己的參賽歷程。一方面是總結經驗,另一方面有了記錄就更有動力去提升,去參加下一次比賽。
在這里插入圖片描述

題目分析

題目鏈接:https://leetcode-cn.com/contest/weekly-contest-284/
還是往常一樣四道題,難度依次提升。

A:找出數組中的所有 K 近鄰下標

簡單模擬,對于每一個key,其附近的2k+1個元素都是合法的,需要注意處理重復。為此我們用一個last變量進行記錄上一次記錄的最后一個元素的位置。

namespace A {class Solution {public:vector<int> findKDistantIndices(vector<int>& nums, int key, int k) {vector<int> ret;int n = nums.size();int last = -1;auto add = [&](int l, int r) {r = min(r, n - 1);l = max(l, last + 1);for (; l <= r; ++l) ret.push_back(l);last = r;};for (int i = 0; i < n; ++i) {if (nums[i] == key) {add(i - k, i + k);}}return ret;}};
}

B:統計可以提取的工件

也是簡單模擬,因為數據量比較小,所以無腦做就可以。如果數據量比較大可能是一道比較有意思的題。

namespace B {class Solution {public:int digArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {vector<vector<bool>> vis(n, vector<bool>(n));for (auto &pr : dig) {vis[pr[0]][pr[1]] = true;}int x0, x1, y0, y1;int ans = 0;auto check = [&](auto &&tool) -> bool {x0 = tool[0]; y0 = tool[1]; x1 = tool[2]; y1 = tool[3];for (int i = x0; i <= x1; ++i) {for (int j = y0; j <= y1; ++j) {if (!vis[i][j]) return false;}}return true;};for (auto &tool : artifacts) {if (check(tool)) ++ans;}return ans;}};
}

C:K 次操作后最大化頂端元素

這個題如果還是想要通過模擬去做那么就會毫無頭緒。因為觀察到最后要求的是棧頂的元素最大。而我們如何進行這k次操作的情況是非常多的,我們應該觀察哪些元素可以通過k次操作放到棧頂。
假如對棧中的元素從1開始編號。如果我們直接出棧k次,那么是可以得到第k+1個元素的,這個也是我們能夠看到的最后一個值。
對1到k-1個元素,我們都可以通過將他們的在最后一步入棧從而讓他們放到棧頂。
需要進行討論的就是我們能夠讓第k個元素放到棧頂?答案是不行(可以通過簡單模擬驗證一下)。下面我們簡單證明一下。
為了讓第k個元素放到棧頂,我們必須彈出前k-1個操作,這樣我們就只能再操作一下,而一下無論是彈出還是插入都不能讓第k個元素放到棧頂。

經過上面的討論,我們發現,其實題目的意思就是讓我們去找前k+1個元素除去第k個元素的最大值。

但是還需要注意的一點是當n為1的情況(有時間我再證明一下,當時沒怎么想清楚在這里還wa了一發)

namespace C {/** 前k - 1的最大值肯定可以取到* 第k個元素取不到* 第k + 1個元素可以取到*/class Solution {public:int maximumTop(vector<int>& nums, int k) {int n = nums.size();if (n == 1 && (k % 2 == 1)) return -1;int ans = -1;int kk = min(k - 1, n);for (int i = 0; i < kk; ++i) {ans = max(ans, nums[i]);}if (k < n) {ans = max(ans, nums[k]);}return ans;}};
}

D:得到要求路徑的最小帶權子圖

這個題差一點點就做出來了,思路是正確的,但是編碼有一個小失誤(忘記了優先隊列元素的含義)

剛開始的思路是求src1和src2到dest的最短路的和,如果兩個的最短路有重復就減去重復的。后來發現的例外:主要是因為減去的那個重復不一定是最大的,存在不是最短路的兩個路徑但是重復的成分很高,整體的和反而更小。

后來再思考了一下,那我不知道那個是重復路徑的起點,不如我遍歷一下,讓每一個都當做起點。這樣子的路徑和就是dis[src1][k]+dis[src2][k]+dis[k][dest]
想到這里我覺得我找到了正確的思路,想要用一下Floyed去求最短路。一看節點個數1e5,然后就意識到肯定會超時。因為Floyed的復雜度是O(n^3)
那么只能進行優化,考慮正向建圖求src1和src2到每個節點的距離,再反向建圖求每個節點到dest的距離。因為數據量很大,所以要求不能使用簡單的Dijkstra,要使用最小堆優化的Dijkstra,這樣每次Djikstra的復雜度是O(nlogn),最后遍歷一下的復雜度是O(n)。

但是在寫Dijkstra的時候我是抄的板子,沒有去理解優先隊列節點的含義,最終導致出錯了,也算是咎由自取吧。

吃了個飯回來又過了,淚目。

namespace D {/** 假如src1在src2到dest的路徑上或者返過來,則是平凡的情況*/class Solution {using ll = long long;struct HeapNode {ll d;int u;HeapNode(ll d_, int u_):d(d_), u(u_){}bool operator <(const HeapNode&rhs) const {return d > rhs.d;}};public:long long minimumWeight(int n, vector<vector<int>>& edges, int src1, int src2, int dest) {vector<vector<pair<int, int>>> graph(n), reverse_graph(n);//建圖int u, v, w;for (auto &edge : edges) {u = edge[0]; v = edge[1]; w = edge[2];graph[u].emplace_back(v, w);reverse_graph[v].emplace_back(u, w);}vector<ll> dis1(n), dis2(n), dis3(n);vector<bool> vis(n);auto dijkstra = [n, &vis](auto &&graph, auto &&dis, int s) {priority_queue<HeapNode> q;for (int i = 0; i < n; ++i) {dis[i] = LONG_LONG_MAX;}dis[s] = 0;for (int i = 0; i < n; ++i) vis[i] = false;q.emplace(0, s);while (!q.empty()) {HeapNode x = q.top(); q.pop();int u = x.u;if (vis[u]) continue;vis[u] = true;//print(u);auto &edges = graph[u];for (auto &pr : edges) {int v = pr.first;int w = pr.second;//print("\t", u ,v ,w);if (dis[v] > dis[u] + w) {dis[v] = dis[u] + w;q.emplace(dis[v], v);}}}};dijkstra(graph, dis1, src1);dijkstra(graph, dis2, src2);dijkstra(reverse_graph, dis3, dest);ll ans = LONG_LONG_MAX;for (int k = 0; k < n; ++k) {if (dis1[k] == LONG_LONG_MAX || dis2[k] == LONG_LONG_MAX || dis3[k] == LONG_LONG_MAX) {continue;}ans = min(ans, dis1[k] + dis2[k] + dis3[k]);}if (ans == LONG_LONG_MAX) return -1;else return ans;}};
}

經驗總結

  • 重復的邊對Dijkstra算法是沒有影響的
  • Dijkstra算法需要的是最小堆,而默認的小于號得到的是最大堆,因此應該在重載小于號的時候讓含義反過來。之所以會出現這樣子是和堆的實際生成有關系(上游下游什么的,已經忘記了,有時間復習一下)
  • 為了避免初始化為正無窮的時候兩個正無窮相加溢出,我們可以在相加前進行判斷。
  • 需要注意Dijkstra對節點標記為已處理是在彈出堆頂元素進行的,而不是在入堆的時候進行的。這一點和一般的BFS不同。Dijkstra算法正確性主要是距離源節點最近的節點的最短路徑已經確認
  • 可以放心大膽地用emplace,雖然不知道為什么有一次在emplace的時候報錯了,當時心態很崩。

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

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

相關文章

Leetcode第286場周賽

緒論 上周因為有事沒有參加周賽&#xff0c;這周沒有錯過。這次周賽拿到了人生第一個AK&#xff0c;參加大大小小的比賽這么多次&#xff0c;從來沒有AK過&#xff0c;淚目了。 感覺這次比賽的思維難度對我來講稍高一些&#xff0c;前三道題就花了一個小時&#xff0c;而以往…

第287場周賽

緒論 雖然是上周日參加的比賽&#xff0c;但是這周沒有怎么學習&#xff0c;每天就是玩耍。也導致對周賽的總結遲遲沒有進行。想著再拖下去下次周賽都要開始了&#xff0c;在這里補一下。 這場比賽總體比上場簡單一些&#xff0c;但是最后一道題因為忘記初始化類內變量導致調試…

第288場周賽

緒論 雖然沒有AK&#xff0c;但是不知道為什么排名比以前AK了都靠前。可能是因為最后一道題有些難度&#xff0c;縮小了我和大佬之間的差距。最后一個小時寫最后一道題&#xff0c;累死累活想了一個貪心遍歷的算法&#xff0c;當時是一直RE&#xff0c;后來下來調了調又WA了。 …

Clion遠程部署和運行

緒論 作為Clion的忠實粉絲&#xff0c;現在的我的幾乎所有的coding都是通過Clion完成。因為需要在服務器上進行開發&#xff0c;又離不開Clion&#xff0c;就了解了如何通過Clion遠程部署和開發。 主要是借鑒了博客&#xff1a;使用Clion優雅的完全遠程自動同步和遠程調試c。如…

C++ 單例模式 call_once : terminate called after throwing an instance of ‘std::system_error‘

在學習了C中可以使用call_once進行初始化資源后&#xff0c;我就想著寫一個單例模板供以后使用。 template<typename T> class SingleTon {using Ptr std::shared_ptr<T>;static Ptr p;static std::once_flag flag;template<typename ...Args>static void …

C++讀寫鎖造成死鎖

C14支持std::shared_timed_mutex C17支持std::shared_mutex 前者相比后者支持的操作更多&#xff0c;但是后者相對性能更好。 使用std::lock_guard<std::shared_mutex>和std::unique_lock<std::shared_mutex>互斥訪問使用std::shared_lock<std::shared_mutex…

每日一題:449. 序列化和反序列化二叉搜索樹

題目分析 題目鏈接&#xff1a;449. 序列化和反序列化二叉搜索樹 覺得序列化很簡單&#xff0c;前序遍歷、后序遍歷、中序遍歷、層序遍歷等等。其中得到前序遍歷和后序遍歷是可以通過遞歸解法反序列化的&#xff0c;覺得這樣子做有點復雜。就想著可不可以一次遍歷。一次遍歷的…

C++高效集合數據結構設計

緒論 在復雜算法實現過程中我們經常會需要一個高效的集合數據結構&#xff0c;支持常數級別的增、刪、查&#xff0c;以及隨機返回、遍歷&#xff0c;最好還能夠支持交集、并集、子集操作 哈希集合實現 大家可能很快想到unordered_set&#xff0c;unordered_set由于底層是哈…

C++ 工具函數庫

在寫一些大型項目的過程中經常需要一些工具函數&#xff0c;例如獲取隨機數、計時器、打印函數、重要常量&#xff08;如最大值&#xff09;、信號與槽等&#xff0c;由于每一個工程都自己手動實現一個實在是太傻&#xff0c;我將其總結放入一個文件中。 utils.h // Copyright…

muduo網絡庫使用入門

muduo網絡庫介紹 muduo網絡庫是陳碩大神開發的基于主從Reactor模式的&#xff0c;事件驅動的高性能網絡庫。 網絡編程中有很多是事務性的工作&#xff0c;使用muduo網絡庫&#xff0c;用戶只需要填上關鍵的業務邏輯代碼&#xff0c;并將回調注冊到框架中&#xff0c;就可以實…

C++ map/unordered_map元素類型std::pair<const key_type, mapped_type>陷阱

在開發的過程中需要遍歷一個unordered_map然后把他的迭代器傳給另一個對象&#xff1a; class A; class B { public:void deal(const std::pair<int, A>& item); }; std::unordered_map<int, A> mp; B b; for (auto &pr : mp) {b.deal(pr); }在我的項目中…

Ubuntu install ‘Bash to dock‘

緒論 在Ubuntu環境搭建這篇博客中記錄了使用Dash To Dock來配置Ubuntu的菜單項&#xff0c;使得實現macOS一樣的效果。為了配置新電腦的環境&#xff0c;我還是想安裝這個軟件。但是如今在Ubuntu Software中已經找不到這個軟件了&#xff0c;我在網上借鑒了一些博客的經驗才得…

Leetcode第309場周賽

Date: September 4, 2022 Difficulty: medium Rate by others: ???? Time consuming: 1h30min 題目鏈接 競賽 - 力扣 (LeetCode) 題目解析 2399. 檢查相同字母間的距離 class Solution {public:bool checkDistances(string s, vector<int>& distance) {vec…

C++ 模板函數、模板類:如果沒有被使用就不會被實例化

C中如果一個模板函數沒有使用過&#xff0c;那么其局部靜態變量都不會被實例化&#xff1a; class A { public:A() {edward::print("A ctor");} };template<typename T> void test() {static A a; }int main() {test<int>(); //如果注釋掉則不會有輸出r…

C++ 條件變量的使用

緒論 并發編程紛繁復雜&#xff0c;其中用于線程同步的主要工具——條件變量&#xff0c;雖然精悍&#xff0c;但是要想正確靈活的運用卻并不容易。 對于條件變量的理解有三個難點&#xff1a; 為什么wait函數需要將解鎖和阻塞、喚醒和上鎖這兩對操作編程原子的&#xff1f;為…

C++Primer學習筆記:第1章 開始

本博客為閱讀《C Primer》&#xff08;第5版&#xff09;的讀書筆記 ps:剛開始的時候我將所有的筆記都放在一篇博客中&#xff0c;等看到第六章的時候發現實在是太多了&#xff0c;導致我自己都不想看&#xff0c;為了日后回顧&#xff08;不那么有心理壓力&#xff09;&#…

【ubuntu】ubuntu14.04上安裝搜狗輸入法

** 在ubuntu14.04.4 desktop 64amd版本上安裝sogou輸入法 ** 0.換安裝源為中國源&#xff08;可選&#xff0c;下載會快些&#xff09; 1.搭fcitx環境 2.安裝sogou for linux 詳細步驟&#xff1a; 因為sogou中文輸入法基于fcitx(Free Chinese Input Toy for X),需要先搭環境…

【ubuntu】ubuntu下用make編譯程序報錯找不到openssl/conf.h

ubuntu下用make編譯程序報錯找不到openssl/conf.h 安裝libssl-dev:i386&#xff0c;sudo apt-get install libssl-dev:i386 看好版本&#xff0c;如果不加i386默認下載的是32位&#xff0c;用ln命令連接過去也還是用不了的!libssl.dev安裝好后&#xff0c;用find / -name libs…

【ubuntu】ubuntu如何改變系統用戶名

ubuntu如何改變系統用戶名 方法1&#xff1a;修改現有用戶名 方法2&#xff1a;創建新用戶&#xff0c;刪掉舊用戶 方法1&#xff1a; * *—&#xff01;&#xff01;&#xff01;有博客說要先改密碼&#xff0c;再改用戶名&#xff0c;否則會出現無法登陸狀況&#xff01;&…

什么是signal(SIGCHLD, SIG_IGN)函數

什么是signal(SIGCHLD, SIG_IGN)函數 在進行網絡編程時候遇到這個函數的使用&#xff0c;自己學習結果如下&#xff0c;有不對請幫忙指正:) signal(SIGCHLD, SIG_IGN)打開manpage康一康~ sighandler_t signal ( int signum, sighandler_t handler );參數1 int signum: 就是…