【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)

Contest 81 (2018年11月8日,周四,凌晨)

链接:https://leetcode.com/contest/weekly-contest-81

比赛情况记录:结果:3/4, ranking: 440/2797。这次题目似乎比较简单,因为我比赛的时候前三题全做出来了(1:12:39),然后第四题有思路,正在写,没写完,比赛完了写完提交也对了。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }

【821】Shortest Distance to a Character(第一题 4分)

给了一个单词(字符串)s,和单词中的任意一个字母 c,问单词中的每个字母到 c 的最近距离是多少。

Example 1:
Input: S = "loveleetcode", C = ‘e‘
Output: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0]

题解:我是用了一个vector记录了所有字符 c 的下标,然后用遍历整个字符串,用一根指针辅助遍历 c 下标数组做的。时间复杂度 O(N)。写法不够优秀,c 的下标数组可以左边右边填一个元素,就不用写那么多判断了吧?

 1 class Solution {
 2 public:
 3     vector<int> shortestToChar(string S, char C) {
 4         const int n = S.size();
 5         vector<int> idxs;
 6         vector<int> ans(n, -1);
 7         for (int i = 0; i < n; ++i) {
 8             if (S[i] == C) {
 9                 idxs.push_back(i);
10                 ans[i] = 0;
11             }
12         }
13         int p1 = 0;
14         for (int i = 0; i < n; ++i) {
15             if (p1 == 0 && i < idxs[p1]) {
16                 ans[i] = idxs[p1] - i;
17             } else if (p1 + 1 < idxs.size() && i >= idxs[p1] && i <= idxs[p1+1]) {
18                 ans[i] = min(abs(i - idxs[p1]), abs(idxs[p1+1] - i));
19             } else if (p1 + 1 == idxs.size() && idxs[p1] < i) {
20                 ans[i] = i - idxs[p1];
21             }
22             if (p1 + 1 < idxs.size() && i == idxs[p1+1]) {
23                 ++p1;
24             }
25         }
26         return ans;
27     }
28 };

【822】Card Flipping Game (第二题 5分)

给了一排纸牌,纸牌前面和后面都有一个数字,我们可以做两个动作,第一个动作是任意翻动任意的纸牌正反面(形成新的正反面数组),第二个动作是我们拿一张纸牌,如果它反面的数字没有在正面的数组里面出现,那么这个数字就是good,要求返回最小 good 的数字。

题解:我是先把 front 和 back 数组合二为一,然后把大数组做了一个排序。然后遍历正反两面的数组,把正反面数字相同的纸牌上的数字放进了一个set里面,这些数字肯定不是 good 的,因为不论这些纸牌怎么翻,都是一个数字。然后我返回了大数组不在set里面的第一个元素。

 1 class Solution {
 2 public:
 3     int flipgame(vector<int>& fronts, vector<int>& backs) {
 4         const int n = fronts.size();
 5         int ans = 0;
 6         vector<int> tot(fronts);
 7         for (auto b : backs) {
 8             tot.push_back(b);
 9         }
10         sort(tot.begin(), tot.end());
11         set<int> st;
12         for (int i = 0; i < n; ++i) {
13             if (fronts[i] == backs[i]) {
14                 st.insert(fronts[i]);
15             }
16         }
17         for (int i = 0; i < 2 * n; ++i) {
18             if (st.find(tot[i]) == st.end()) {
19                 ans = tot[i];
20                 break;
21             }
22         }
23         return ans;
24     }
25 };

【820】Short Encoding of Words (第三题 6分)(尝试了一下翻译题目,不好翻译,直接贴原题了)

Given a list of words, we may encode it by writing a reference string S and a list of indexes A.

For example, if the list of words is ["time", "me", "bell"], we can write it as S = "time#bell#" and indexes = [0, 2, 5].

Then for each index, we will recover the word by reading from the reference string from that index until we reach a "#" character.

What is the length of the shortest reference string S possible that encodes the given words?

Example:
Input: words = ["time", "me", "bell"]
Output: 10
Explanation: S = "time#bell#" and indexes = [0, 2, 5].
Note:
1 <= words.length <= 2000.
1 <= words[i].length <= 7.
Each word has only lowercase letters.

题解:我一开始想的是把相同后缀的字符串用map分组,然鹅,代码写出来了但是超时。后来仔细想了一下,相同的后缀如果翻转一下字符串就能变成相同的前缀,然后按照字母序sort一下,就能逐条比较了。最后的时间复杂度降低成了O(nlogn),(要排序的复杂度)

 1 class Solution {
 2 public:
 3     int minimumLengthEncoding(vector<string>& words) {
 4         const int n = words.size();
 5         vector<string> newWords(words);
 6         for (auto& w : newWords) {
 7             reverse(w.begin(), w.end());
 8         }
 9         sort(newWords.begin(), newWords.end());
10         vector<string> temp;
11         for (int i = 0; i < n-1; ++i) {
12             string cur = newWords[i], ne = newWords[i+1];
13             int curSize = cur.size(), neSize = ne.size();
14             if (neSize < curSize || ne.substr(0, curSize) != cur) {
15                 temp.push_back(cur);
16                 continue;
17             }
18         }
19         temp.push_back(newWords.back());
20         int ans = 0;
21         for (auto w : temp) {
22             ans += (1 + w.size());
23         }
24         return ans;
25
26     }
27 };

【823】Binary Trees With Factors (第四题 7 分)

给了一个 unique 的数组 A,题目定义说二叉树的一个非叶子结点的值一定等于它左右儿子的乘积,问这个数组能组成多少种类的二叉树,数组中的元素可以用任意次。因为答案可能很大,所以需要模 1e9 + 7.

Example 1:
Input: A = [2, 4]
Output: 3
Explanation: We can make these trees: [2], [4], [4, 2, 2]

Example 2:
Input: A = [2, 4, 5, 10]
Output: 7
Explanation: We can make these trees: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2].

题解:我首先一个感觉就是应该先每个元素能表达成乘积形式的东西列出来。比如 4 -> (2, 2); 10 ->(2, 5), (5,2)。然后枚举每一个元素为根,然后我开始纠结了一下,难道要dfs吗?结果那么多,我估计dfs不是超时就是要挂。所以就往 dp 上面想。

dp[i] 表示以 A[i] 为根的二叉树的种类,如果 A[i] = A[x] * A[y],那么dp[i] = dp[x] * dp[y]。dp[i] 初始化为 1, 因为这棵树可以选择没有孩子,只有它自己作为根。

然后就是 MOD 了。这种大数我就是容易写挂,不知道为啥,是不是还有什么原理没有摸透。唉。

 1 class Solution {
 2 public:
 3     const int MOD = 1e9 + 7;
 4     int numFactoredBinaryTrees(vector<int>& A) {
 5         int n = A.size();
 6         sort(A.begin(), A.end());
 7         map<int, vector<pair<int, int>>> mp, debugMap;
 8         for (int i = 1; i < n; ++i) {
 9             int p1 = 0, p2 = i - 1;
10             while (p1 <= p2) {
11                 int mul = A[p1] * A[p2];
12                 if (A[i] == mul) {
13                     debugMap[A[i]].push_back(make_pair(A[p1], A[p2]));
14                     mp[i].push_back(make_pair(p1, p2));
15                     if (A[p1] != A[p2]) {
16                         debugMap[A[i]].push_back(make_pair(A[p2], A[p1]));
17                         mp[i].push_back(make_pair(p2, p1));
18                     }
19                     p1++, p2--;
20                 } else if (A[i] > mul) {
21                     ++p1;
22                 } else if (A[i] < mul) {
23                     --p2;
24                 }
25             }
26         }
27         vector<long long> dp(n, 1); //dp[i] 表示用 A[i] 为根的二叉树有几棵
28         for (int i = 0; i < n; ++i) {
29             //int root = A[i];
30             if (mp.find(i) == mp.end()) {continue;}
31             vector<pair<int, int>> vec = mp[i];
32             for (auto p : vec) {
33                 int x = p.first, y = p.second;
34                 dp[i] = (dp[i] + dp[x] * dp[y]) % MOD;
35             }
36         }
37         int ans = 0;
38         for (auto e : dp) {
39             ans = (ans + e) % MOD;
40         }
41         return ans;
42     }
43 };

Contest 82 (2018年11月8日,周四)

链接:https://leetcode.com/contest/weekly-contest-82

比赛情况记录:结果:3/4, ranking:345/2564。这次四道题都不难,我比赛做出来三题,有个逻辑判断的题想了比较久, friends of appropriate ages,这个题推导了半天。第四题没空写了,结果第四题下午写WA了好几次。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }

Goat Latin(第一题 4分)

Friends Of Appropriate Ages(第二题 5分)(这题也要看答案)

Most Profit Assigning Work (第三题 7分)(感觉这题还能更快,要记得看答案)

Making A Large Island (第四题 8 分)

Contest 83 (2018年11月12日,周一)

链接:https://leetcode.com/contest/weekly-contest-83

比赛情况记录:比赛结果记录:2/4。 ranking:675/2688。好像这场是随便做了两题签到题就有事出去了orz。(11月21日才写log,有点忘记了orz)第三题我有印象,好像做了,然而超时啊啊啊啊啊。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
span.Apple-tab-span { white-space: pre }

【830】Positions of Large Groups (第一题 3分)

给了一个小写字母的字符串,每一段相同的字母叫做一个 group, 如果 group 的字母数量 大于等于 3个字符就叫做 large group。返回所有 large group 的开始和结束下标。

Input: "abcdddeeeeaabbbcd"
Output: [[3,5],[6,9],[12,14]]

题解:两根指针扫一遍。

 1 class Solution {
 2 public:
 3     vector<vector<int>> largeGroupPositions(string S) {
 4         const int n = S.size();
 5         vector<vector<int>> ans;
 6         int p1 = 0, p2 = 0;
 7         while (p2 < n) {
 8             while (p2 < n && S[p1] == S[p2]) {
 9                 p2++;
10             }
11             if (p2 - p1 >= 3) {
12                 ans.push_back({p1, p2-1});
13             }
14             p1 = p2;
15         }
16         return ans;
17     }
18 };

【831】Masking Personal Information (第二题 5分)

给了一个字符串,可能是 email address 也可能是 phone number。题目的意思要给这个字符串打码。

如果是 email 的字符串,它一定满足这个格式:"[email protected]",给它 masking 的方法是 name1 只留首尾两个字母,其他的name保留原来格式,但是 所有的 name 都必须是小写字母。

如果是 phone number, 它可能有国家地区编码,也可能没有。一个 phone number 的长度是 10 - 13 个数字,最后 10个数字做 local number,前面可能有 1 - 3 个数字做 country-code。local number masking 之后要保留这个格式:"***-***-DDDD"。

如果有 country-code 的话,country-code 前面的 ‘+’ 和后面的 ‘-’ 需要保留。

Example 1:
Input: "[email protected]"
Output: "l*****[email protected]"
Explanation: All names are converted to lowercase, and the letters between the
             first and last letter of the first name is replaced by 5 asterisks.
             Therefore, "leetcode" -> "l*****e".

Example 2:
Input: "[email protected]"
Output: "a*****[email protected]"
Explanation: There must be 5 asterisks between the first and last letter
             of the first name "ab". Therefore, "ab" -> "a*****b".

Example 3:
Input: "1(234)567-890"
Output: "***-***-7890"
Explanation: 10 digits in the phone number, which means all digits make up the local number.

Example 4:
Input: "86-(10)12345678"
Output: "+**-***-***-5678"
Explanation: 12 digits, 2 digits for country code and 10 digits for local number. 

题解:模拟题,读懂题意开始搞就行了。

 1 class Solution {
 2 public:
 3     string maskPII(string S) {
 4         const int n = S.size();
 5         if (S.find("@") != string::npos && S.find(".") != string::npos) {
 6             return copeEmail(S);
 7         }
 8         return copePhone(S);
 9     }
10     string copeEmail(string S) {
11         auto pos = S.find("@");
12         string name1 = S.substr(0, pos);
13         for (auto& p : name1) {
14             if (isupper(p)) {
15                 p = tolower(p);
16             }
17         }
18         string name2 = S.substr(pos);
19         //printf("pos = %d, name1 = %s, name2 = %s \n", pos, name1.c_str(), name2.c_str());
20         string newName1 = string(1, name1.front()) + "*****" + string(1, name1.back());
21         for (auto& p : name2) {
22             if (isupper(p)) {
23                 p = tolower(p);
24             }
25         }
26         S = newName1 + name2;
27         return S;
28     }
29     string copePhone(string S) {
30         string newS = "";
31         for (auto p : S) {
32             if (isdigit(p)) {
33                 newS += p;
34             }
35         }
36         const int n = newS.size();
37         if (n < 10) {cout << "err" << endl;}
38         if (n == 10) {
39             S = "***-***-" + newS.substr(n-4);
40         } else {
41             int countryCodeNum = n  - 10;
42             string countryCode(countryCodeNum, ‘*‘);
43             S = "+" + countryCode + "-" +  "***-***-" + newS.substr(n-4);
44         }
45         return S;
46     }
47 };

【829】Consecutive Numbers Sum(第三题 7分)

给了一个数字 N,返回它有几种拆法能把它表示成一段连续的自然数相加。

Example 1:
Input: 5
Output: 2
Explanation: 5 = 5 = 2 + 3
Example 2:
Input: 9
Output: 3
Explanation: 9 = 9 = 4 + 5 = 2 + 3 + 4
Example 3:
Input: 15
Output: 4
Explanation: 15 = 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5
Note: 1 <= N <= 10 ^ 9.

题解:我好像在哪个地方见过这个题,然而解法超时。解法就是用 两个变量 small 和 big,一开始他们两个都是 1, 如果现在的 [small, big] 区间和 summ 小于 N,就 ++big,这样 summ 就会变大。如果现在的 [small, big] 区间和 summ 大于 N,就 ++small, 这样 summ 就会减小。这个是超时解法,时间复杂度应该是 O(N)。(吐了)

【828】Unique Letter String(第四题 9分)

Contest 84 (2018年11月21日,周三)

链接:https://leetcode.com/contest/weekly-contest-84

比赛情况记录:

Contest 85 (还没做,待定)

Contest 86 (2018年11月21日,周三)

链接:https://leetcode.com/contest/weekly-contest-86

比赛情况记录:

原文地址:https://www.cnblogs.com/zhangwanying/p/9926472.html

时间: 2024-08-30 05:20:24

【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)的相关文章

【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)

Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653-656) 链接:https://leetcode.com/contest/leetcode-weekly-contest-44 比赛情况记录:就做出来两题,第三题不难,然而就是在算坐标的时候卡住了.orz.结果:2/4,ranking:637/2272.第四题没看题,第三题搞得心情不好了orz. [653]Two Sum

【Leetcode周赛】从contest-71开始。(一般是10个contest写一篇文章)

Contest 71 () Contest 72 () Contest 73 (2019年1月30日模拟) 链接:https://leetcode.com/contest/weekly-contest-73 Contest 74 (2019年1月31日模拟) 链接:https://leetcode.com/contest/weekly-contest-74 Contest 75 (2019年1月31日模拟) 链接:https://leetcode.com/contest/weekly-conte

【Leetcode周赛】从contest-121开始。(一般是10个contest写一篇文章)

Contest 121 (题号981-984)(2019年1月27日) 链接:https://leetcode.com/contest/weekly-contest-121 总结:2019年2月22日补充的报告.当时不想写.rank:1093/3924,AC:2/4.还是太慢了. [984]String Without AAA or BBB(第一题 4分)(Greedy, M) 给了两个数字,A 代表 A 个 'A', B 代表 B 个'B' 在字符串里面.返回一个可行的字符串,字符串中包含 A

【Leetcode周赛】比赛目录索引

contest 1 ~ contest 10 contest 11 ~ contest 20 contest 21 ~ contest 30 : https://www.cnblogs.com/zhangwanying/p/6753040.html contest 31 ~ contest 40 contest 41 ~ contest 50 contest 51 ~ contest 60:https://www.cnblogs.com/zhangwanying/p/9998523.html c

[leetcode 周赛 157] 1217 玩筹码

1217 Play With Chips 玩筹码 题目描述 数轴上放置了一些筹码,每个筹码的位置存在数组 chips 当中. 你可以对 任何筹码 执行下面两种操作之一(不限操作次数,0 次也可以): 将第 i 个筹码向左或者右移动 2 个单位,代价为 0. 将第 i 个筹码向左或者右移动 1 个单位,代价为 1. 最开始的时候,同一位置上也可能放着两个或者更多的筹码. 返回将所有筹码移动到同一位置(任意位置)上所需要的最小代价. 示例 1: 输入:chips = [1,2,3] 输出:1 解释:

[leetcode 周赛 157] 1218 最长定差子序列

1218 Longest Arithmetic Subsequence of Given Difference 最长定差子序列 问题描述 给你一个整数数组 arr 和一个整数 difference,请你找出 arr 中所有相邻元素之间的差等于给定 difference 的等差子序列,并返回其中最长的等差子序列的长度. 示例 1: 输入:arr = [1,2,3,4], difference = 1 输出:4 解释:最长的等差子序列是 [1,2,3,4]. 示例 2: 输入:arr = [1,3,

[leetcode 周赛 157] 1219 黄金矿工

1219 Path with Maximum Gold 黄金矿工 问题描述 你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m * n 的网格 grid 进行了标注.每个单元格中的整数就表示这一单元格中的黄金数量:如果该单元格是空的,那么就是 0. 为了使收益最大化,矿工需要按以下规则来开采黄金: 每当矿工进入一个单元,就会收集该单元格中的所有黄金. 矿工每次可以从当前位置向上下左右四个方向走. 每个单元格只能被开采(进入)一次. 不得开采(进入)黄金数目为 0 的单元

[leetcode 周赛 159] 1233 删除子文件夹

1233 Remove Sub-Folders from the Filesystem 删除子文件夹 问题描述 你是一位系统管理员,手里有一份文件夹列表 folder,你的任务是要删除该列表中的所有 子文件夹,并以 任意顺序 返回剩下的文件夹. 我们这样定义「子文件夹」: 如果文件夹?folder[i]?位于另一个文件夹?folder[j]?下,那么?folder[i]?就是?folder[j]?的子文件夹. 文件夹的「路径」是由一个或多个按以下格式串联形成的字符串: /?后跟一个或者多个小写英

[leetcode 周赛 159] 1235 规划兼职工作

1235 Maximum Profit in Job Scheduling 规划兼职工作 问题描述 你打算利用空闲时间来做兼职工作赚些零花钱. 这里有?n?份兼职工作,每份工作预计从?startTime[i]?开始到?endTime[i]?结束,报酬为?profit[i]. 给你一份兼职工作表,包含开始时间?startTime,结束时间?endTime?和预计报酬?profit?三个数组,请你计算并返回可以获得的最大报酬. 注意,时间上出现重叠的 2 份工作不能同时进行. 如果你选择的工作在时间