日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[算法]LeetCode第194场周赛202006021

發布時間:2023/12/14 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [算法]LeetCode第194场周赛202006021 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第194場周賽

20200621

1486. 數組異或操作

題目描述1

給你兩個整數,n 和 start 。

數組 nums 定義為:nums[i] = start + 2*i(下標從 0 開始)且 n == nums.length 。

請返回 nums 中所有元素按位異或(XOR)后得到的結果。

示例 1:

輸入:n = 5, start = 0 輸出:8 解釋:數組 nums 為 [0, 2, 4, 6, 8],其中 (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8 。"^" 為按位異或 XOR 運算符。

示例 2:

輸入:n = 4, start = 3 輸出:8 解釋:數組 nums 為 [3, 5, 7, 9],其中 (3 ^ 5 ^ 7 ^ 9) = 8.

示例 3:

輸入:n = 1, start = 7 輸出:7

示例 4:

輸入:n = 10, start = 5 輸出:2

提示:

  • 1 <= n <= 1000
  • 0 <= start <= 1000
  • n == nums.length

Solution1

class Solution {public int xorOperation(int n, int start) {int ans = start;for(int i = 1; i < n; i++){ans ^= (start + 2 * i);}return ans;} }

1487. 保證文件名唯一

題目描述2

給你一個長度為 n 的字符串數組 names 。你將會在文件系統中創建 n 個文件夾:在第 i 分鐘,新建名為 names[i] 的文件夾。

由于兩個文件 不能 共享相同的文件名,因此如果新建文件夾使用的文件名已經被占用,系統會以 (k) 的形式為新文件夾的文件名添加后綴,其中 k 是能保證文件名唯一的 最小正整數 。

返回長度為 n 的字符串數組,其中 ans[i] 是創建第 i 個文件夾時系統分配給該文件夾的實際名稱。

示例 1:

輸入:names = ["pes","fifa","gta","pes(2019)"] 輸出:["pes","fifa","gta","pes(2019)"] 解釋:文件系統將會這樣創建文件名: "pes" --> 之前未分配,仍為 "pes" "fifa" --> 之前未分配,仍為 "fifa" "gta" --> 之前未分配,仍為 "gta" "pes(2019)" --> 之前未分配,仍為 "pes(2019)"

示例 2:

輸入:names = ["gta","gta(1)","gta","avalon"] 輸出:["gta","gta(1)","gta(2)","avalon"] 解釋:文件系統將會這樣創建文件名: "gta" --> 之前未分配,仍為 "gta" "gta(1)" --> 之前未分配,仍為 "gta(1)" "gta" --> 文件名被占用,系統為該名稱添加后綴 (k),由于 "gta(1)" 也被占用,所以 k = 2 。實際創建的文件名為 "gta(2)" 。 "avalon" --> 之前未分配,仍為 "avalon"

示例 3:

輸入:names = ["onepiece","onepiece(1)","onepiece(2)","onepiece(3)","onepiece"] 輸出:["onepiece","onepiece(1)","onepiece(2)","onepiece(3)","onepiece(4)"] 解釋:當創建最后一個文件夾時,最小的正有效 k 為 4 ,文件名變為 "onepiece(4)"。

示例 4:

輸入:names = ["wano","wano","wano","wano"] 輸出:["wano","wano(1)","wano(2)","wano(3)"] 解釋:每次創建文件夾 "wano" 時,只需增加后綴中 k 的值即可。

示例 5:

輸入:names = ["kaido","kaido(1)","kaido","kaido(1)"] 輸出:["kaido","kaido(1)","kaido(2)","kaido(1)(1)"] 解釋:注意,如果含后綴文件名被占用,那么系統也會按規則在名稱后添加新的后綴 (k) 。

提示:

  • 1 <= names.length <= 5 * 10^4
  • 1 <= names[i].length <= 20
  • names[i] 由小寫英文字母、數字和/或圓括號組成。

Solution2

首先想到的是用hashset來判斷出沒出現過,但是會超時

要改成hashmap,用map里的value用來保存key出現的次數,這樣就避免了超時

//這樣寫會超時 class Solution {public String[] getFolderNames(String[] names) {Set<String> set = new HashSet<>();String[] ans = new String[names.length];int i = 0;for(String name : names){if(!set.contains(name)){set.add(name);ans[i++] = name;}else{//存在 加后綴int num = 1;String name1 = name;while(set.contains(name)){String k = String.valueOf(num);name = name1 + "(" + k + ")";num++;}set.add(name);ans[i++] = name;}}return ans;} } class Solution {public String[] getFolderNames(String[] names) {// 用map里的value用來保存key出現的次數,這樣就避免了超時Map<String,Integer> map = new HashMap<>();String[] ans = new String[names.length];int i = 0;for(String name : names){if(!map.containsKey(name)){//map中不存在,直接寫入答案對應位置map.put(name, 1);ans[i++] = name;}else{//map中存在//取出之前出現的次數int count = map.get(name);// 后面有沒有出現過while(map.containsKey(name + "(" + count + ")")){count++;}// 更新mapmap.put(name + "(" + count + ")", 1);map.put(name, map.get(name) + 1);ans[i++] = name + "(" + count + ")";}}return ans;} }

1488. 避免洪水泛濫

題目描述3

你的國家有無數個湖泊,所有湖泊一開始都是空的。當第 n 個湖泊下雨的時候,如果第 n 個湖泊是空的,那么它就會裝滿水,否則這個湖泊會發生洪水。你的目標是避免任意一個湖泊發生洪水。

給你一個整數數組 rains ,其中:

rains[i] > 0 表示第 i 天時,第 rains[i] 個湖泊會下雨。
rains[i] == 0 表示第 i 天沒有湖泊會下雨,你可以選擇 一個 湖泊并 抽干 這個湖泊的水。
請返回一個數組 ans ,滿足:

ans.length == rains.length
如果 rains[i] > 0 ,那么ans[i] == -1 。
如果 rains[i] == 0 ,ans[i] 是你第 i 天選擇抽干的湖泊。
如果有多種可行解,請返回它們中的 任意一個 。如果沒辦法阻止洪水,請返回一個 空的數組 。

請注意,如果你選擇抽干一個裝滿水的湖泊,它會變成一個空的湖泊。但如果你選擇抽干一個空的湖泊,那么將無事發生(詳情請看示例 4)。

示例 1:

輸入:rains = [1,2,3,4] 輸出:[-1,-1,-1,-1] 解釋:第一天后,裝滿水的湖泊包括 [1] 第二天后,裝滿水的湖泊包括 [1,2] 第三天后,裝滿水的湖泊包括 [1,2,3] 第四天后,裝滿水的湖泊包括 [1,2,3,4] 沒有哪一天你可以抽干任何湖泊的水,也沒有湖泊會發生洪水。

示例 2:

輸入:rains = [1,2,0,0,2,1] 輸出:[-1,-1,2,1,-1,-1] 解釋:第一天后,裝滿水的湖泊包括 [1] 第二天后,裝滿水的湖泊包括 [1,2] 第三天后,我們抽干湖泊 2 。所以剩下裝滿水的湖泊包括 [1] 第四天后,我們抽干湖泊 1 。所以暫時沒有裝滿水的湖泊了。 第五天后,裝滿水的湖泊包括 [2]。 第六天后,裝滿水的湖泊包括 [1,2]。 可以看出,這個方案下不會有洪水發生。同時, [-1,-1,1,2,-1,-1] 也是另一個可行的沒有洪水的方案。

示例 3:

輸入:rains = [1,2,0,1,2] 輸出:[] 解釋:第二天后,裝滿水的湖泊包括 [1,2]。我們可以在第三天抽干一個湖泊的水。 但第三天后,湖泊 1 和 2 都會再次下雨,所以不管我們第三天抽干哪個湖泊的水,另一個湖泊都會發生洪水。

示例 4:

輸入:rains = [69,0,0,0,69] 輸出:[-1,69,1,1,-1] 解釋:任何形如 [-1,69,x,y,-1], [-1,x,69,y,-1] 或者 [-1,x,y,69,-1] 都是可行的解,其中 1 <= x,y <= 10^9

示例 5:

輸入:rains = [10,20,20] 輸出:[] 解釋:由于湖泊 20 會連續下 2 天的雨,所以沒有沒有辦法阻止洪水。

提示:

  • 1 <= rains.length <= 10^5
  • 0 <= rains[i] <= 10^9

Solution3

優先隊列+貪心,每次抽干最近要下雨的湖

class Solution {public int[] avoidFlood(int[] rains) {int n = rains.length;int[] ans = new int[n];int[] next = new int[n];//記錄每個湖下一次的下雨時間Arrays.fill(next, n+1);Map<Integer, Integer> tm = new HashMap<>();//每個湖最早下雨的時間 湖-天數for(int i = n-1; i >= 0; i--){int r = rains[i];if(r > 0){if(tm.containsKey(r)){next[i] = tm.get(r);}tm.put(r, i); //更新第r個湖下雨的時間}}Map<Integer, Boolean> st = new HashMap<>();//湖泊的狀態PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<>((o1, o2) -> o1.getKey()-o2.getKey());//小根堆,value-湖泊編號,key-這個湖泊下一次最早哪天下雨for(int i = 0; i < n; i++){int r = rains[i];if(r > 0){// 如果這天下雨了if(st.getOrDefault(r, false) == true){//如果這個湖泊之前已經有水了,則洪水發生return new int[]{};}st.put(r, true);pq.offer(new Pair(next[i], r));ans[i] = -1;}else{// 如果這天沒有下雨,要抽水if(pq.isEmpty()){ans[i] = 1;//如果堆是空的,則抽第一個湖}else{//取出最近要下雨的,這個湖抽水的需求最迫切。也就是堆的key最小的Pair<Integer, Integer> t = pq.poll();st.put(t.getValue(), false);ans[i] = t.getValue();}}}return ans;} }

參考:

  • https://www.bilibili.com/video/BV1ja4y1Y7nk
  • https://leetcode-cn.com/problems/avoid-flood-in-the-city/solution/you-xian-ji-dui-lie-tan-xin-mei-ci-xian-chou-gan-z/

1489. 找到最小生成樹里的關鍵邊和偽關鍵邊

題目描述4

給你一個 n 個點的帶權無向連通圖,節點編號為 0 到 n-1 ,同時還有一個數組 edges ,其中 edges[i] = [fromi, toi, weighti] 表示在 fromi 和 toi 節點之間有一條帶權無向邊。最小生成樹 (MST) 是給定圖中邊的一個子集,它連接了所有節點且沒有環,而且這些邊的權值和最小。

請你找到給定圖中最小生成樹的所有關鍵邊和偽關鍵邊。如果從圖中刪去某條邊,會導致最小生成樹的權值和增加,那么我們就說它是一條關鍵邊。偽關鍵邊則是可能會出現在某些最小生成樹中但不會出現在所有最小生成樹中的邊。

請注意,你可以分別以任意順序返回關鍵邊的下標和偽關鍵邊的下標。

提示:

  • 2 <= n <= 100
  • 1 <= edges.length <= min(200, n * (n - 1) / 2)
  • edges[i].length == 3
  • 0 <= fromi < toi < n
  • 1 <= weighti <= 1000
  • 所有 (fromi, toi) 數對都是互不相同的。

Solution4

最小生成樹:構造最小生成樹的算法主要有:克魯斯卡爾(Kruskal)算法和普利姆(Prim)算法

class Solution {/** 思路詳解:* 1. 整體思路:* a. 通過Kruska算法(加邊法)可以計算出最小生成樹MST的最小權值minCost* b. 遍歷所有的邊:* i. 如果去掉這個邊,MST的最小權值 > minCost,說明這個邊是一個關鍵邊* ii. 否則,說明如果去掉這個邊,MST的最小權值 == minCost,這個又分為兩種情況* 1) 如果包含這個邊的MST的最小權值 == minCost, 說明這個邊是一個偽關鍵邊* 2) 否則,說明包含這個邊的MST的最小權值 > minCost,說明這個邊一定不是關鍵邊* 2. getMSTExclude / getMSTInclude 算法:* a. 初始化ends數組,值為-1,表示每個節點都是樹的終點* b. newEdges是按照權值從小到大排列的有序數組,遍歷數組,對于每條邊的兩個節點,如果他們不連通,則連接這兩個節點對應的兩顆樹* c. 最終的結果有兩種可能,通過n-1條邊把樹連通為一顆樹(返回邊權值),或者最終不足以連通為一顆樹(返回最大整數)*/public List<List<Integer>> findCriticalAndPseudoCriticalEdges(int n, int[][] edges) {int height = edges.length;int[][] newEdges = new int[height][4];for(int i = 0; i < height; i++){newEdges[i][0] = edges[i][0];newEdges[i][1] = edges[i][1];newEdges[i][2] = edges[i][2];newEdges[i][3] = i;}Arrays.sort(newEdges, new Comparator<int[]>(){@Overridepublic int compare(int[] o1, int[] o2){return o1[2] - o2[2];}});List<Integer> realCri = new ArrayList<>();List<Integer> fakeCri = new ArrayList<>();int minCost = getMSTExclude(n, newEdges, -1);for(int i = 0; i < height; i++){if(getMSTExclude(n, newEdges, i) > minCost){realCri.add(i);}else if(getMSTInclude(n, newEdges, i) == minCost){fakeCri.add(i);}}List<List<Integer>> ans = new ArrayList<>();ans.add(realCri);ans.add(fakeCri);return ans;}//不包含邊edge的MSTprivate int getMSTExclude(int n, int[][] edges, int edge){int height = edges.length;int[] ends = new int[n];//記錄每個節點指向的終點Arrays.fill(ends, -1);//-1代表指向自己int cost = 0;int counter = 0;for(int[] e : edges){if(e[3] == edge){//排除edge邊continue;}int end1 = getEnd(ends, e[0]);int end2 = getEnd(ends, e[1]);if(end1 != end2){//連接兩條邊ends[end1] = end2;cost += e[2];counter++;}}return counter == n - 1 ? cost : Integer.MAX_VALUE;}//包含邊edge的MSTprivate int getMSTInclude(int n, int[][] edges, int edge){int height = edges.length;int[] ends = new int[n];//記錄每個節點指向的終點Arrays.fill(ends, -1);//-1代表指向自己int cost = 0;int counter = 0;//連接edge邊for(int[] e : edges){if(e[3] == edge){ends[e[0]] = e[1];cost += e[2];counter++;}}for(int[] e : edges){int end1 = getEnd(ends, e[0]);int end2 = getEnd(ends, e[1]);if(end1 != end2){//連接兩條邊ends[end1] = end2;cost += e[2];counter++;}}return counter == n - 1 ? cost : Integer.MAX_VALUE;}//值為-1的才是樹的終點private int getEnd(int[] ends, int node){if(ends[node] == -1){return node;}else{ends[node] = getEnd(ends, ends[node]);return ends[node];}} }

參考鏈接:https://leetcode-cn.com/problems/find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree/solution/kruskasuan-fa-by-xiao-hei-34/

我的公眾號:GitKid

暫時每日分享LeetCode,我在不斷學習的過程中,公眾號也在不斷充實,歡迎大家掃碼關注。

TODO:《劍指offer》系列

總結

以上是生活随笔為你收集整理的[算法]LeetCode第194场周赛202006021的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。