上一周的第139周赛由于时间冲突没有参加,这次就参加了第140周赛。
这周的周赛题主要是暴力,做题主要先实现,具体是不是最优的先不管,要优化都是赛后的事情了。
因为开始学习新的语言Java,因此最近的每日做题(可看我主页的置顶帖)和周赛几乎都优先用Java语言来做,有一些题还是用了最习惯的C++来做。
像第一道题,字符串分割题,之前用C++做是比较麻烦了,但Java和Python之类的有 split() 函数使用,所以方便了不少。语言是工具,哪个方便用哪个。
1. Bigram 分词(Occurrences After Bigram)
AC代码(Java)
2. 活字印刷(Letter Tile Possibilities)
AC代码(Java)
3.根到叶路径上的不足节点(Insufficient Nodes in Root to Leaf Paths)
AC代码(Java)
4.不同字符的最小子序列(Smallest Subsequence of Distinct Characters)
AC代码(C++)
LeetCode第140场周赛地址:
https://leetcode-cn.com/contest/weekly-contest-140/
https://leetcode-cn.com/contest/weekly-contest-140/problems/occurrences-after-bigram/
给出第一个词
first
和第二个词second
,考虑在某些文本text
中可能以 "first second third
" 形式出现的情况,其中second
紧随first
出现,third
紧随second
出现。对于每种这样的情况,将第三个词 "
third
" 添加到答案中,并返回答案。示例 1:
输入:text = "alice is a good girl she is a good student", first = "a", second = "good" 输出:["girl","student"]
示例 2:
输入:text = "we will we will rock you", first = "we", second = "will" 输出:["we","rock"]
提示:
1 <= text.length <= 1000
text
由一些用空格分隔的单词组成,每个单词都由小写英文字母组成1 <= first.length, second.length <= 10
first
和second
由小写英文字母组成
题目意思很直接,就是给定一个字符串文本 text,给定两个字符串单词,找出文本中跟着这两个单词后的第三个单词(可能有多个)。
这道题的难点主要就是将字符串文本text 进行分割,分割成多个字符串单词,然后进行匹配,如果按顺序匹配上了,那按顺序下去的第三个就是答案(可能会有多个)。
字符串分割可以使用到 split() 函数,根据题目,字符串只用空格分割,所以分割依据就是根据空格进行分割。得到一个字符串数组。
然后遍历这个数组,判断该位置 i 和下一个位置 i+1 是不是和给定的 first和 second相等,相等的话,则将 i+2 位置上的字符串保存下来。不相等,则遍历下一个 i 。
其中代码中用到了 ArrayList 这个相当于C++中的 vector
class Solution {
public String[] findOcurrences(String text, String first, String second) {
String[] words = text.split(" ");
int res = 0;
ArrayList ans = new ArrayList();
for(int i = 0;i < words.length-2;++i)
{
if(words[i].equals(first) && words[i+1].equals(second))
{
ans.add(words[i+2]);
}
}
return ans.toArray(new String[ans.size()]) ;
}
}
https://leetcode-cn.com/contest/weekly-contest-140/problems/letter-tile-possibilities/
你有一套活字字模
tiles
,其中每个字模上都刻有一个字母tiles[i]
。返回你可以印出的非空字母序列的数目。示例 1:
输入:"AAB" 输出:8 解释:可能的序列为 "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA"。
示例 2:
输入:"AAABBC" 输出:188
提示:
1 <= tiles.length <= 7
tiles
由大写英文字母组成
根据题目与提示,字符串的总长度最多为7,所以可以利用DFS来枚举出所有组合的情况,然后统计不同的数量进行输出。
在看这道题前,先要知道如何输出所有组合和全排列
可以参考我的另一篇博客:求一个数组里的数的所有组合和全排列(Java)
所以回到本题中,是第二种情况,我们先将字符串的变成一个整型数组,因为本题是要求求数量有多少个,所以把输出那部分变成一个计数,同时DFS函数的返回值就是目前有几个数,最后将这些数加起来进行输出即可。
class Solution {
public static int DFS(List candidate, String prefix, HashSet hs){
int res = 0;
if(prefix.length()!=0 && !hs.contains(prefix)){
hs.add(prefix);
res++;
}
for(int i=0; i temp = new LinkedList(candidate);
int item = (int)temp.remove(i); // 删除表示这个用过了
res += DFS(temp, prefix+item, hs);
}
return res;
}
public int numTilePossibilities(String tiles) {
Integer[] array = new Integer[tiles.length()];
for(int i = 0;i < tiles.length();++i)
{
array[i] = tiles.charAt(i) - '0';
}
int res = 0;
List list = Arrays.asList(array);
HashSet hs = new HashSet();
res += DFS(list, "", hs);
return res;
}
}
https://leetcode-cn.com/contest/weekly-contest-140/problems/insufficient-nodes-in-root-to-leaf-paths/
给定一棵二叉树的根
root
,请你考虑它所有 从根到叶的路径:从根到任何叶的路径。(所谓一个叶子节点,就是一个没有子节点的节点)假如通过节点
node
的每种可能的 “根-叶” 路径上值的总和全都小于给定的limit
,则该节点被称之为「不足节点」,需要被删除。请你删除所有不足节点,并返回生成的二叉树的根。
提示:
- 给定的树有
1
到5000
个节点-10^5 <= node.val <= 10^5
-10^9 <= limit <= 10^9
利用树的前序搜索,从根节点出发,一直求到最后叶节点,然后判断。
如果是叶节点了,即左右两边为 null,此时我们将 limit 一直减去节点的值,这样子在最后叶节点的时候,如果叶节点此时的 limit小于0,说明这个叶节点是要去掉的。
如果不是叶节点,那么就继续递归走下去,即从左右两下继续下去,此时要注意,本来这个节点还是有至少一个叶节点的,但是如果最后判断,叶节点都没有了,说明叶节点都不够,那么这个根节点就是「不足节点」需要被删掉的。
判断最后都没有返回,那就说明这个节点是有效的,直接返回原本的节点即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode sufficientSubset(TreeNode root, int limit) {
if (root == null) return null;
limit -= root.val;
if (root.left == null && root.right == null) {
if (limit > 0)
return null;
else
return root;
}
else
{
// 本来是还有节点的,但是经过节点判断后,节点失效,所以这个也会被删掉,如例子3。
if (root.left != null)
root.left = sufficientSubset(root.left, limit);
if (root.right != null)
root.right = sufficientSubset(root.right, limit);
if (root.left == null && root.right == null)
return null;
}
return root;
}
}
https://leetcode-cn.com/contest/weekly-contest-140/problems/smallest-subsequence-of-distinct-characters/
返回字符串
text
中按字典序排列最小的子序列,该子序列包含text
中所有不同字符一次。示例 1:
输入:"cdadabcc" 输出:"adbc"
示例 2:
输入:"abcd" 输出:"abcd"
提示:
1 <= text.length <= 1000
text
由小写英文字母组成
利用贪心的方法,使用C++中的stack。
计算每一个字母在字符串中的最后位置,同时一个数组 vis 记录这个字母是否已经在栈中。然后从头遍历字符串。
然后分为以下几个情况
1、此时栈是空的,直接放进
2、栈不空,但这个字母已经放过了(不能重复),所以跳过
3、栈不空,而且这个字母没在里面。分为两个情况:①该字母比栈顶的元素大,直接放进。②字母比栈顶的元素小,判断栈顶是不是最后一个,如果不是最后一个,就取出,依次循环,直到栈顶的元素是最后一个为止。
所以总结上面:
1、字母已经放过了,那就跳过
2、栈不空,同时栈顶元素大过此时字母,同时栈顶元素不是最后一个,那就是第四点的②
3、其他:直接放进
class Solution {
public:
string smallestSubsequence(string text) {
vector last(26,0);
vector vis(26,0);
stack ans;
for(int i=0;ii&&e<=ans.top())
{
vis[ans.top()]=0;
ans.pop();
}
if(!vis[e]){vis[e]=1;ans.push(e);} // 其他情况,放进去后,就把该字母标记为放过
}
string res = "";
while(!ans.empty())
{
char r = ans.top()+'a';
res = r+res;
ans.pop();
}
return res;
}
};