LeetCode之Weekly Contest 101
前一段时间比较忙,而且做这个对于我来说挺耗时间的,已经间隔了几期的没做总结了,后面有机会补齐。而且本来做这个的目的就是为了防止长时间不做把编程拉下,不在追求独立作出所有题了。以后完赛后稍微尝试下,做不出来的直接放弃。
第一题:问题
问题:900. RLE 迭代器
编写一个遍历游程编码序列的迭代器。
迭代器由 RLEIterator(int[] A)
初始化,其中 A
是某个序列的游程编码。更具体地,对于所有偶数i
,A[i]
告诉我们在序列中重复非负整数值 A[i + 1]
的次数。
迭代器支持一个函数:next(int n)
,它耗尽接下来的 n
个元素(n >= 1
)并返回以这种方式耗去的最后一个元素。如果没有剩余的元素可供耗尽,则 next
返回 -1
。
例如,我们以 A = [3,8,0,9,2,5]
开始,这是序列 [8,8,8,5,5]
的游程编码。这是因为该序列可以读作 “三个零,零个九,两个五”。
示例:
输入:["RLEIterator","next","next","next","next"], [[[3,8,0,9,2,5]],[2],[1],[1],[2]]
输出:[null,8,8,5,-1]
解释:
RLEIterator 由 RLEIterator([3,8,0,9,2,5]) 初始化。
这映射到序列 [8,8,8,5,5]。
然后调用 RLEIterator.next 4次。 .next(2) 耗去序列的 2 个项,返回 8。现在剩下的序列是 [8, 5, 5]。 .next(1) 耗去序列的 1 个项,返回 8。现在剩下的序列是 [5, 5]。 .next(1) 耗去序列的 1 个项,返回 5。现在剩下的序列是 [5]。 .next(2) 耗去序列的 2 个项,返回 -1。 这是由于第一个被耗去的项是 5,
但第二个项并不存在。由于最后一个要耗去的项不存在,我们返回 -1。
提示:
0 <= A.length <= 1000
A.length
是偶数。0 <= A[i] <= 10^9
- 每个测试用例最多调用
1000
次RLEIterator.next(int n)
。 - 每次调用
RLEIterator.next(int n)
都有1 <= n <= 10^9
。
链接:https://leetcode-cn.com/contest/weekly-contest-101/problems/rle-iterator/
分析:
看到例子没怎么想,直接试图构建原始数据,然后next更新下标,根据下标直接返回,结果测试中数据很大,懒惰,想当然了。
最终做法是将原始数据建立坐标和值的映射关系,一个data数组,一个index数组(其实就相当于map),然后有变量记录下标,下标值大于index值后,更新到下一个,如果在其范围内,返回对应的数字。
比如例子给出的数据,处理后是:
3 8
5 5
表示坐标3一下的对应值是8,5一下的对应值是5。
AC Code:
class RLEIterator {
public:
vector<long long> datas; //保存数据
vector<long long> sizes; //保存坐标
long long location; //数组坐标
long long datalocation; //当前数字坐标
long long size; //总个数
int endflag; //一旦某个坐标返回-1,后面next都返回-1,做一个优化
public:
RLEIterator(vector<int> A)
{
this->location = 0;
this->datalocation = 0;
this->size = 0;
this->endflag = 0; for (int i = 0; i < A.size(); i+=2)
{
this->size += A[i];
if (A[i] == 0)
{
continue;
}
if (i == 0)
{
this->sizes.emplace_back(A[i]);
}
else
{
this->sizes.emplace_back(A[i] + this->sizes[this->sizes.size()-1]);
} this->datas.emplace_back(A[i+1]);
} } int next(int n)
{
if (this->endflag == 1)
{
return -1;
}
if (this->datalocation + n>=this->size)
{
this->endflag = 1;
return -1;
}
this->datalocation += n; while (this->datalocation > this->sizes[this->location])
{
this->location += 1;
}
return this->datas[this->location];
}
};
其他:
1.第一code
class RLEIterator {
int[] a;
int p = ; public RLEIterator(int[] A) {
a = A;
p = ;
} public int next(int n) {
if(p >= a.length)return -;
n--;
int ret = -;
while(n > ){
if(p >= a.length)return -;
int ex = Math.min(a[p], n);
n -= ex;
a[p] -= ex;
if(a[p] > ){
break;
}else{
p += ;
}
}
while(p < a.length && a[p] == )p += ;
if(p < a.length)ret = a[p+];
n = ; while(n > ){
if(p >= a.length)return -;
int ex = Math.min(a[p], n);
n -= ex;
a[p] -= ex;
if(n == )break;
p += ;
}
return ret;
}
}
2.中间有遇到一个问题,思路什么都多,提交错误,然后调试发现数据范围int是不够的。
第二题:901. 股票价格跨度
问题:
编写一个 StockSpanner
类,它收集某些股票的每日报价,并返回该股票当日价格的跨度。
今天股票价格的跨度被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。
例如,如果未来7天股票的价格是 [100, 80, 60, 70, 60, 75, 85]
,那么股票跨度将是 [1, 1, 1, 2, 1, 4, 6]
。
示例:
输入:["StockSpanner","next","next","next","next","next","next","next"], [[],[100],[80],[60],[70],[60],[75],[85]]
输出:[null,1,1,1,2,1,4,6]
解释:
首先,初始化 S = StockSpanner(),然后:
S.next(100) 被调用并返回 1,
S.next(80) 被调用并返回 1,
S.next(60) 被调用并返回 1,
S.next(70) 被调用并返回 2,
S.next(60) 被调用并返回 1,
S.next(75) 被调用并返回 4,
S.next(85) 被调用并返回 6。 注意 (例如) S.next(75) 返回 4,因为截至今天的最后 4 个价格
(包括今天的价格 75) 小于或等于今天的价格。
提示:
- 调用
StockSpanner.next(int price)
时,将有1 <= price <= 10^5
。 - 每个测试用例最多可以调用
10000
次StockSpanner.next
。 - 在所有测试用例中,最多调用
150000
次StockSpanner.next
。 - 此问题的总时间限制减少了 50%。
链接:https://leetcode-cn.com/contest/weekly-contest-101/problems/online-stock-span/
分析:
如果前一天的股票不大于今天的股票,就可以将其添加的今天的上面,然后将前一天的边界处再次进行判断。
如给出的例子中,
1 | 2 | 3 | 4 | 5 | 6 | 7 |
100 | 80 | 60 | 70 | 60 | 75 | 85 |
第一天100,最大连续天数1
第二天80,小于昨天,最大连续天数1
第三条60,小于昨天,最大连续天数1
第四天70,大于昨天,最大连续天数为1+昨天的连续天数1=2,同时查看前一天的80,大于70,第四天最大连续天数2
第五天60,小于昨天,最大连续天数1
第六天75,大于昨天,加上昨天的连续天数1+1,同时查看边界,即第四天,70<75,加上第四天的连续长度2,查看这一天的边界,即第二天,80>75,则最终最大连续天数为1+1+2=4
第七天85,大于昨天,最大连续天数1+4,查看前一天的边界,即第2天,80<85,加上改天的长度1,查看对比边界100>85,最终连续长度1+4+1=6
AC Code:
class StockSpanner {
public:
private:
vector<long long> datas;
vector<long long> longest;
public:
StockSpanner()
{ } int next(int price)
{
if (this->datas.size() == )
{
//diyici
this->datas.emplace_back(price);
this->longest.emplace_back();
return ;
}
else
{
this->datas.emplace_back(price);
if (this->datas[this->datas.size() - ] > price)
{
this->longest.emplace_back();
return ;
}
else
{ int localindex = this->longest.size()-;
int ret = +this->longest[localindex];
localindex -= this->longest[localindex];
while (localindex>= && price>= this->datas[localindex])
{
ret += this->longest[localindex];
localindex -= this->longest[localindex];
}
this->longest.emplace_back(ret);
return ret; } }
}
};
其他:
1.第一code
class StockSpanner {
int[] stack;
int[] value;
int sp;
int gen = ; public StockSpanner() {
stack = new int[];
value = new int[];
sp = ;
gen = ;
} public int next(int price) {
while(sp > && value[sp-] <= price){
sp--;
}
int ret = gen - (sp == ? - : stack[sp-]);
stack[sp] = gen++;
value[sp] = price;
sp++;
return ret;
}
}
第三题:最大为 N 的数字组合
问题:
我们有一组排序的数字 D
,它是 {'1','2','3','4','5','6','7','8','9'}
的非空子集。(请注意,'0'
不包括在内。)
现在,我们用这些数字进行组合写数字,想用多少次就用多少次。例如 D = {'1','3','5'}
,我们可以写出像 '13', '551', '1351315'
这样的数字。
返回可以用 D
中的数字写出的小于或等于 N
的正整数的数目。
示例 1:
输入:D = ["1","3","5","7"], N = 100
输出:20
解释:
可写出的 20 个数字是:
1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
示例 2:
输入:D = ["1","4","9"], N = 1000000000
输出:29523
解释:
我们可以写 3 个一位数字,9 个两位数字,27 个三位数字,
81 个四位数字,243 个五位数字,729 个六位数字,
2187 个七位数字,6561 个八位数字和 19683 个九位数字。
总共,可以使用D中的数字写出 29523 个整数。
提示:
D
是按排序顺序的数字'1'-'9'
的子集。1 <= N <= 10^9
链接:https://leetcode-cn.com/contest/weekly-contest-101/problems/numbers-at-most-n-given-digit-set/
分析:
1.如果数字位数低于目标数字,肯定满足要求
2.如果位数相同,如果首位小于目标数字最高位,则剩下数字可以随意组合
通用的,如果最高位数字、次高位数字相同,剩下的位数可以随意组合,如此递归直到数字完全相同。
3.n个数字,组成m位数字,有n^m种组发。
AC Code:
class Solution {
public: int atMostNGivenDigitSet(vector<string>& D, int N)
{
//先组成所有的数字,然后挑选满足条件的结果
//首先拿到N的位数length,从D中挑选任意数字累计重复length次,得到所有可能的数字
//大小为D.size^length,太多了,需要优化
//关键是位数相同的一个,低于的位数可以直接计算指数,位数低一定满足
//更关键的是最高位, long long ret = ;
vector<int> datas;
for (long long i = ; i < D.size(); i++)
{
datas.emplace_back(D[i][] - '');
}
if (GetLength(N) == )
{
return GetLessOrEqlN(datas, N).size();
}
long long num1 = GetSameLengthNums(datas, N);
long long num2 = GetLowLengthNums(datas.size(), N / );
ret = num1 + num2;
return ret;
}
long long GetLowLengthNums(int size, int N)
{
long long length = GetLength(N);
if (size == ) //1个数字组成任何位数数字都只有1种组发
{
return length;
}
long long ret = ;
while (length>)
{
ret += (int)pow(size, length);
length--;
}
return ret;
}
long long GetSameLengthNums(vector<int> datas, int N)
{
long long ret = ; while (N)
{
if (N < )
{
ret += GetLessOrEqlN(datas, N).size(); //如果是10以下的数字,直接找到所有不大于该数的个数即可
break;
}
int length = GetLength(N);
int num = N / ((int)pow(, length-));
ret += GetLessN(datas, num).size()*(int)pow(datas.size(), length-);
int findflag = ; //如果高位有相同的,还需要对比次高位,直到拼出相等数字
for (int i = ; i < datas.size(); i++)
{
int tmp = datas[i] - num;
if (tmp==)
{
findflag = ;
break;
}
}
if (findflag == )
{
//cout << "no target,break" << endl;
break;
}
N %= ((int)pow(, length - ));
if (GetLength(N) + != length)
{
break;
}
} return ret;
}
vector<int> GetLessN(vector<int> org, int n)
{
vector<int> ret;
for (int i = ; i < org.size(); i++)
{
if (org[i] < n)
{
ret.emplace_back(org[i]);
}
}
return ret;
}
vector<int> GetLessOrEqlN(vector<int> org, int n)
{
vector<int> ret;
for (int i = ; i < org.size(); i++)
{
if (org[i] <= n)
{
ret.emplace_back(org[i]);
}
}
return ret;
}
int GetLength(int N)
{
int ret = ;
while (N)
{
ret++;
N /= ;
}
return ret;
}
};
其他:
1.第一code
class Solution {
public int atMostNGivenDigitSet(String[] D, int N) {
int mask = ;
for(String s : D){
mask ^= <<s.charAt()-'';
}
char[] s = Integer.toString(N+).toCharArray();
long dp = ;
int e = ;
for(int i = ;i < s.length;i++){
dp *= Integer.bitCount(mask); for(int j = ;j < s[i]-'';j++){
if(mask<<~j<){
dp+=e;
}
}
if(i > ){
dp += Integer.bitCount(mask);
}
if(mask<<~(s[i]-'')>=){
e = ;
}
}
return (int)dp;
}
}
直接将N+1,避免了==的额外处理,这个思路非常好。
2.手残将复制写作==,折腾了半天才发现,单步调试直接优化跳过了,还以为数据类型问题导致不能直接对比。
3.做的时候大体code完成之后简单测试通过,提价错误,解决提交,又有错误,再次解决,感觉在不停的在打补丁,一方面说明思路不完整,没能直接覆盖到所有情况,另一方面进一步暴露出测试数据设计上的不足,之前就有发现这个问题,不过感觉没多少提高,实际上在周赛的时候一般只是测试下例子,基本没有构造数据测试,关键是没时间,其次能力不足,难以短时间构建出合理的数据。好在编写的测试函数能够将所有的测试用例都保存下,一旦修改code可以将之前测过的所有数据测一遍,避免解决一个问题导致前面的测例failed。
第四题:DI 序列的有效排列
问题:
我们给出 S
,一个源于 {'D', 'I'}
的长度为 n
的字符串 。(这些字母代表 “减少” 和 “增加”。)
有效排列 是对整数 {0, 1, ..., n}
的一个排列 P[0], P[1], ..., P[n]
,使得对所有的 i
:
- 如果
S[i] == 'D'
,那么P[i] > P[i+1]
,以及; - 如果
S[i] == 'I'
,那么P[i] < P[i+1]
。
有多少个有效排列?因为答案可能很大,所以请返回你的答案模 10^9 + 7
.
示例:
输入:"DID"
输出:5
解释:
(0, 1, 2, 3) 的五个有效排列是:
(1, 0, 3, 2)
(2, 0, 3, 1)
(2, 1, 3, 0)
(3, 0, 2, 1)
(3, 1, 2, 0)
提示:
1 <= S.length <= 200
S
仅由集合{'D', 'I'}
中的字符组成。
链接:https://leetcode-cn.com/contest/weekly-contest-101/problems/valid-permutations-for-di-sequence/
分析:
这种大数据类型一直都很头疼,放弃不折腾了
AC Code:
其他:
第一code
class Solution {
public int numPermsDISequence(String S) {
int n = S.length();
int[] a = new int[n+];
int p = ;
int len = ;
for(int i = ;i < n;i++){
if(S.charAt(i) == 'D'){
len++;
}else{
a[p++] = len+;
len = ;
}
}
a[p++] = len+; int mod = ;
long[][] C = new long[ + ][ + ];
for (int i = ; i <= ; i++) {
C[i][] = ;
for (int j = ; j <= i; j++) {
C[i][j] = C[i - ][j - ] + C[i - ][j];
if (C[i][j] >= mod)
C[i][j] -= mod;
}
} a = Arrays.copyOf(a, p);
long[] dp = new long[p+];
dp[] = ;
int all = ;
for(int i = ;i <= p;i++){
all += a[i-];
int s = ;
for(int j = i-, sgn = ;j >= ;j--, sgn = -sgn){
s += a[j];
dp[i] += dp[j] * C[all][s] * sgn;
dp[i] %= mod;
}
if(dp[i] < )dp[i] += mod;
}
return (int)dp[p];
}
}
检举作弊
总结:
TI8那一次没参加周赛,其他的几次都参加了,但是总结没做,有的是有完成四道题,有的还没做完,还有一个有写到草稿箱,第四个没完成所以没发布。工作了,有很多事情要做,很难专注算法的提高与练习,而且本身天赋有限,有些问题如果想搞懂需要花太多的时间与精力,虽说当初开始的目的就是增长见识,性格使然还是一直在尽量做出所有问题,努力追求完美,结果更不完美。以后要逐渐学会放弃,不管做到什么程度,尽量周二晚前完成总结。
学习不易,坚持更难,继续努力吧。
LeetCode之Weekly Contest 101的更多相关文章
- LeetCode之Weekly Contest 102
第一题:905. 按奇偶校验排序数组 问题: 给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素. 你可以返回满足此条件的任何数组作为答案. 示例: 输入: ...
- LeetCode之Weekly Contest 92
第一题:转置矩阵 问题: 给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9] ...
- LeetCode之Weekly Contest 93
第一题:二进制间距 问题: 给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离. 如果没有两个连续的 1,返回 0 . 示例 1: 输入:22 输出:2 解释: 22 的 ...
- LeetCode之Weekly Contest 91
第一题:柠檬水找零 问题: 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10 ...
- LeetCode之Weekly Contest 90
LeetCode第90场周赛记录 第一题:亲密字符串 问题: 给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true :否则返回 ...
- LeetCode Weekly Contest 8
LeetCode Weekly Contest 8 415. Add Strings User Accepted: 765 User Tried: 822 Total Accepted: 789 To ...
- Leetcode Weekly Contest 86
Weekly Contest 86 A:840. 矩阵中的幻方 3 x 3 的幻方是一个填充有从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等. 给定一个 ...
- leetcode weekly contest 43
leetcode weekly contest 43 leetcode649. Dota2 Senate leetcode649.Dota2 Senate 思路: 模拟规则round by round ...
- LeetCode Weekly Contest 23
LeetCode Weekly Contest 23 1. Reverse String II Given a string and an integer k, you need to reverse ...
随机推荐
- 如何删除.DS_Store文件?
.DS_Store出现在Desktop和其它地方,看它碍眼,它是什么,详见百度百科 http://baike.baidu.com/link?url=yLTDHR6OS66-981wpCY-mWPF7a ...
- NSPhotoLibraryAddUsageDescription解决办法
图片并保存到本地的功能,一点发现闪退了.发现 Xcode 报以下错误: The app's Info.plist must contain an NSPhotoLibraryAddUsageDescr ...
- MySQL 的视图、触发器、事务、存储过程、函数
MySQL 的视图.触发器.事务.存储过程.函数 阅读目录 一 视图 二 触发器 三 事务 四 存储过程 五 函数 六 流程控制 一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句 ...
- 2017"百度之星"程序设计大赛 - 初赛(A)小C的倍数问题
Problem Description 根据小学数学的知识,我们知道一个正整数x是3的倍数的条件是x每一位加起来的和是3的倍数.反之,如果一个数每一位加起来是3的倍数,则这个数肯定是3的倍数. 现在给 ...
- curl_setopt 注意
最近碰到好多奇怪的BUG,今天就是一个例子. 我在用CURL调用麦考林的接口,在浏览器测试完全没问题,调用全都成功.但是用命令行执行PHP时,却一直不行,返回http code 302错误.百思不得其 ...
- 获取所有bean的名字
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.facto ...
- Proto.Actor模型
Proto.Actor模型 http://proto.actor/ https://github.com/axzxs2001/ProtoActorSample https://www.cnblogs. ...
- Smarty中的请求变量和保留变量的使用范例
PHP中提供的超全局数组 Smarty中对应的请求变量 $_GET <{$smarty.get}> $_POST ...
- MVC 知识点总结
[此篇文章收录于其他博客,作为笔记使用] 一· MVC MVC设计模式->MVC框架(前端开发框架),asp.net(webform) aspx M:Model (模型,负责业务逻辑处理,比如 ...
- VS2012快捷键消失
我也是网上搜的不过我认为挺有效就自己摘录下来了,具体原作者也找不到,所以就下手了,望原谅. 开始菜单 -->所有程序-->Visual Studio 2012文件夹 --> Visu ...