【周赛复盘】LeetCode第298场单周赛

_LEON_

关注

阅读 132

2022-07-27


目录

  • ​​1、兼具大小写的最好英文字母​​
  • ​​1)题目描述​​
  • ​​2)原题链接​​
  • ​​3)思路解析​​
  • ​​4)模板代码​​
  • ​​5)算法与时间复杂度​​
  • ​​2、个位数字为 K 的整数之和​​
  • ​​1)题目描述​​
  • ​​2)原题链接​​
  • ​​3)思路解析​​
  • ​​4)模板代码​​
  • ​​5)算法与时间复杂度​​
  • ​​3、小于等于 K 的最长二进制子序列​​
  • ​​1)题目描述​​
  • ​​2)原题链接​​
  • ​​3)思路解析​​
  • ​​4)模板代码​​
  • ​​5)算法与时间复杂度​​
  • ​​4、卖木头块​​
  • ​​1)题目描述​​
  • ​​2)原题链接​​
  • ​​3)思路解析​​
  • ​​4)模板代码​​
  • ​​5)算法与时间复杂度​​
  • ​​5、周赛总结​​

1、兼具大小写的最好英文字母

1)题目描述

给你一个由英文字母组成的字符串 ​​s​​​ ,请你找出并返回 ​​s​​中的 最好 英文字母。返回的字母必须为大写形式。如果不存在满足条件的字母,则返回一个空字符串。
最好 英文字母的大写和小写形式必须 在 ​​s​​​ 中出现。
英文字母 ​​​b​​​ 比另一个英文字母 ​​a​更好 的前提是:英文字母表中,​​b​​​ 在 ​​a​​ 之 出现。

2)原题链接

​​LeetCode.5242:兼具大小写的最好英文字母

3)思路解析

  • 简单的模拟题,判断某个字母的大小写是否同时出现在字符串中即可,字典序越大的优先级越高。考虑使用字符映射去记录即可。下面我使用的是​​​int​​​数组去记录,题目只要求是否存在,使用​​boolean​​数组也可。

4)模板代码

class Solution {
int[] a=new int[26];
int[] b=new int[26];
public String greatestLetter(String s) {
char[] str=s.toCharArray();
for (int i = 0; i < str.length; i++) {
char c=str[i];
if('a'<=c&&c<='z') a[c-'a']++;
else if ('A'<=c&&c<='Z') b[c-'A']++;
}
String ans="";
for (int i = 0; i < 26; i++) {
if (a[i]!=0&&b[i]!=0){
ans=(char)(i+'A')+"";
}
}
return ans;
}
}

5)算法与时间复杂度

  算法:模拟
  时间复杂度:遍历一次字符串,复杂度为

2、个位数字为 K 的整数之和

1)题目描述

给你两个整数 ​​num​​​和 ​​k​​ ,考虑具有以下属性的正整数多重集:

  • 每个整数个位数字都是​​k ​​。
  • 所有整数之和是​​num​​​ 。
    返回该多重集的最小大小,如果不存在这样的多重集,返回​​​-1​​​ 。
    注意:
  • 多重集与集合类似,但多重集可以包含多个同一整数,空多重集的和为 0 。
  • 个位数字是数字最右边的数位。

【周赛复盘】LeetCode第298场单周赛_职场和发展_03

2)原题链接

​​LeetCode.5218:个位数字为 K 的整数之和

3)思路解析

  • 可以很明显发现,假设我们数组中放了个数,这个数的和为,且每个数的个位数都为,那么我们很明显发现需要满足下面这个等式:
  • 这是因为的个位只由这个数的个位之和的个位数决定,而个数的个位数都是已知,所以我们需要去枚举到最小的,使得满足上述的等式,此时即为答案。
  • 对于需要特判一下,当相乘的数进入循环后说明没有找到答案直接返回​​-1​​。比如
    ​2​​无论和谁相乘,答案的个位数永远都是​​02468​​,判断到重复说明不可能组成题意要求的。当然的过程中也需要保证

4)模板代码

class Solution {
public int minimumNumbers(int num, int k) {
//特判
if(num==0) return 0;
if(k>num) return -1;
//s是我们需要找的数字
int s=num%10;
Set<Integer> set=new HashSet<>();
//区间足够大即可
for (int i = 1; i <3000; i++) {
int g=k*i;
//不能超过num
if(g>num) return -1;
//找到答案
if (g%10==s) return i;
//找完了,没找到答案返回-1
if (!set.add(g%10)) return -1;
}
//无法到达的步骤
return -1;
}
}

class Solution {

public int minimumNumbers(int num, int k) {
if (num == 0) {
return 0;
}
for (int i = 1, j = num - k; i <= 10 && j >= 0; i++, j -= k) {
if (j % 10 == 0) {
return i;
}
}
return -1;
}
}

5)算法与时间复杂度

  算法:数学
  时间复杂度:结论题,不需要多少时间,视为

3、小于等于 K 的最长二进制子序列

1)题目描述

给你一个二进制字符串 ​​s​​​ 和一个正整数 ​​k​​​ 。
请你返回 s 的 最长 子序列,且该子序列对应的 二进制 数字小于等于 ​​k​​​ 。
注意:

  • 子序列可以有前导 0 。
  • 空字符串视为​​0​​ 。
  • 子序列是指从一个字符串中删除零个或者多个字符后,不改变顺序得到的剩余字符序列。

2)原题链接

​​LeetCode.5218:小于等于 K 的最长二进制子序列

3)思路解析

  • 考虑一个二进制字符串,如​​​1000110​​​,它的十进制应该是:

    从右往左的每个所代表的值分别是,幂数为它们从右往左数的下标(从​​​0​​开始)。
  • 由于题意说可以包含前导​​​0​​​,我们可知它并不会影响我们​​1​​​的位置让我们的二进制数变大,但后面的​​0​​​会导致​​1​​​的位置向左移动导致值变大。比如​​0000001000110​​​并不大,​​1000011000000​​却非常大。
  • 从贪心的角度出发,为了选出更多的前导​​​0​​​以及让每个​​1​​​的价值尽可能小,我们从末尾开始选择,对于每个​​0​​​我们直接计入答案,对于每个​​1​​​我们去判断加上它当前的价值和是否超出​​k​​,如果不超则加上否则不加。
  • 注意精度问题,就已经接近超出​​​int​​​,所以需要判断,​​k​​​的最大值也仅达到

4)模板代码

class Solution {
public int longestSubsequence(String s, int k) {
char[] c=s.toCharArray();
int ans=0;
int res=0;
int pre=0;
for (int i = c.length-1; i >=0; i--) {
if (c[i]=='1'&&pre<=30){
int h=(int)Math.pow(2,pre);
if (ans+h<=k){
ans+=h;
res++;
}
}else if(c[i]=='0') res++;
pre++;
}
return res;
}
}

5)算法与时间复杂度

  算法:贪心
  时间复杂度:遍历了一遍字符串,复杂度为

4、卖木头块

1)题目描述

给你两个整数 ​​m​​​ 和 ​​n​​​ ,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 ​​prices​​​ ,其中 ​​prices[i] = [hi, wi, pricei]​​​ 表示你可以以 ​​pricei​​​ 元的价格卖一块高为 ​​hi​​​ 宽为 ​​wi​​​ 的矩形木块。
每一次操作中,你必须按下述方式之一执行切割操作,以得到两块更小的矩形木块:

  • 沿垂直方向按高度完全切割木块,或
  • 沿水平方向按宽度完全切割木块

2)原题链接

​​LeetCode.5254:卖木头块

3)思路解析

  • 不难发现,每个木块都是矩阵,且每个木块的价值只与高和宽有关,与位置无关,且矩阵切割后仍然为矩阵。从角度出发。
  • 定义的含义为高为,宽为的木块可卖出的最大价值。对于任意一块高为宽为矩形木块我们可以枚举切割位置,我们可以按位置切割为两块矩阵,也可以按宽切割为两块矩阵。还需要考虑是否可以不切割直接进行售卖,三者取最大值。所以转移方程为

4)模板代码

class Solution {
int N=210;
long[][] f=new long[N][N];
long[][] map=new long[N][N];
public long sellingWood(int m, int n, int[][] prices) {
for (int[] p:prices){
map[p[0]][p[1]]=p[2];
}
for (int i = 1; i <=m; i++) {
for (int j = 1; j <=n; j++) {
f[i][j]=map[i][j];
for (int k = 1; k <i; k++) {
f[i][j]=Math.max(f[i][j],f[k][j]+f[i-k][j]);
}
for (int k = 1; k <j; k++) {
f[i][j]=Math.max(f[i][j],f[i][k]+f[i][j-k]);
}
}
}
return f[m][n];
}
}

5)算法与时间复杂度

  算法:dp
  时间复杂度:

5、周赛总结


精彩评论(0)

0 0 举报