好几周没打周赛了,今天打了一次,第一次ak,感动。下面是本次周赛。
第一题、检查单词是否为句中其他单词的前缀
难度:easy,链接:5416. 检查单词是否为句中其他单词的前缀
给你一个字符串 sentence 作为句子并指定检索词为 searchWord ,其中句子由若干用 单个空格 分隔的单词组成。
请你检查检索词 searchWord 是否为句子 sentence 中任意单词的前缀。
如果 searchWord 是某一个单词的前缀,则返回句子 sentence 中该单词所对应的下标(下标从 1 开始)。
如果 searchWord 是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。
如果 searchWord 不是任何单词的前缀,则返回 -1 。字符串 S 的 「前缀」是 S 的任何前导连续子字符串。
输入:sentence = "i love eating burger", searchWord = "burg"
输出:4
解释:"burg" 是 "burger" 的前缀,而 "burger" 是句子中第 4 个单词。
题解:先把句子split,然后从头开始判断是否是前缀,是就break然后返回当前单词下标即可。
代码:
class Solution {
public int isPrefixOfWord(String sentence, String searchWord) {
String[] words = sentence.split(" ");
int len = searchWord.length();
for (int i = 0; i < words.length; i++){
if (words[i].length() >=len && words[i].substring(0,len).equals(searchWord)){
return i + 1;
}
}
return -1;
}
}
第二题:定长子串中元音的最大数目
难度:中等, 链接:5417. 定长子串中元音的最大数目
题目:
给你字符串 s 和整数 k 。
请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。
英文中的 元音字母 为(a, e, i, o, u)。
输入:s = "abciiidef", k = 3 输出:3 解释:子字符串 "iii" 包含 3 个元音字母。 输入:s = "aeiou", k = 2 输出:2 解释:任意长度为 2 的子字符串都包含 2 个元音字母
题解:滑动窗口题,窗口大小为k,每次滑动计算元音字母数
代码:
class Solution {
public boolean isvalid(char c)//判断字母是否是元音字母
{
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c== 'u'){
return true;
}else{
return false;
}
}
public int maxVowels(String s, int k) {
int len = s.length();
int res = 0;
int num = 0;
for (int i = 0 ; i < k; i++)//窗口初始元音字母数
{
if (isvalid(s.charAt(i))){
num++;
}
}
res = num;
for (int i = k; i < len ; i++)//窗口滑动
{
if (isvalid(s.charAt(i))){
num++;
}
if (isvalid(s.charAt(i - k))){
num--;
}
res = Math.max(res,num);
}
return res;
}
}
第三题、 二叉树中的伪回文路径
题目:
给你一棵二叉树,每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的,当它满足:路径经过的所有节点值的排列中,存在一个回文序列。
请你返回从根到叶子节点的所有路径中 伪回文 路径的数目。
示例 1:
输入:root = [2,3,1,3,1,null,1]
输出:2
解释:上图为给定的二叉树。总共有 3 条从根到叶子的路径:红色路径 [2,3,3] ,绿色路径 [2,1,1] 和路径 [2,3,1] 。
在这些路径中,只有红色和绿色的路径是伪回文路径,因为红色路径 [2,3,3] 存在回文排列 [3,2,3] ,绿色路径 [2,1,1] 存在回文排列 [1,2,1] 。
将题目分解:找到所有的根到叶子的路径和判断路径是否是回文路径两个问题。第一个问题可以dfs解决,第二个问题因为一个回文路径只能有一个或0个奇数的数字个数,比如101只有1个奇数数字个数(1个0),11只有0个奇数数字个数(0个0),12因为有2个奇数数字个数(1个1,1个2),怎么排列都不是回文数,所以不是伪回文路径。所以这道题解法就出来了,dfs求出所有路径,然后用map存储数字个数判断(因为只有9个数字,所以判断也不慢)。这种是暴力解法,也可以dfs的时候就判断,可以快一点
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int res = 0;
HashMap<Integer,Integer> map = new HashMap();
public int pseudoPalindromicPaths (TreeNode root) {
map.put(root.val,map.getOrDefault(root.val,0) + 1);
dfs(root);
return res;
}
void dfs(TreeNode root)
{
if (root.left == null && root.right == null){
if (isvalid(map))res++;
return;
}
if (root.left != null)
{
map.put(root.left.val,map.getOrDefault(root.left.val,0) + 1);
dfs(root.left);
map.put(root.left.val,map.get(root.left.val) - 1);
}
if (root.right != null)
{
map.put(root.right.val,map.getOrDefault(root.right.val,0) + 1);
dfs(root.right);
map.put(root.right.val,map.get(root.right.val) - 1);
}
}
boolean isvalid(HashMap<Integer,Integer> map){
int odds = 0;
for (Integer i:map.values())
{
if (i % 2 == 1) odds++;
}
if (odds <= 1) return true;
else return false;
}
}
第四题、 两个子序列的最大点积
难度:困难 链接:5419. 两个子序列的最大点积
题目:
给你两个数组 nums1 和 nums2 。
请你返回 nums1 和 nums2 中两个长度相同的 非空 子序列的最大点积。
数组的非空子序列是通过删除原数组中某些元素(可能一个也不删除)后剩余数字组成的序列,但不能改变数字间相对顺序。比方说,[2,3,5] 是 [1,2,3,4,5] 的一个子序列而 [1,5,3] 不是。
输入:nums1 = [2,1,-2,5], nums2 = [3,0,-6]
输出:18
解释:从 nums1 中得到子序列 [2,-2] ,从 nums2 中得到子序列 [3,-6] 。
它们的点积为 (2*3 + (-2)*(-6)) = 18 。
题解:这道题如果能联想到最长公共子序列那题的话,就迎刃而解了,一个模板。
dp[i][j] = max(dp[i-1][j],dp[i][j-1],max(0,dp[i-1][j-1] + nums1[i]) * nums2[j]);//dp[i][j]为nums1的前i个数字形成的子数组和nums2的前j个数字形成的子数组的长度相同的非空子序列的最大点积。
代码:
class Solution {
public int maxDotProduct(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int[][] dp = new int[len1][len2];//dp[i][j]为nums1的前i个数字形成的子数组和nums2的前j个数字形成的子数组的长度相同的非空子序列的最大点积。
dp[0][0] = nums1[0] * nums2[0];
for (int i = 1; i < len1;i++)
{
dp[i][0] = Math.max(dp[i-1][0] , nums1[i] * nums2[0]);
}
for (int i = 1; i < len2;i++)
{
dp[0][i] = Math.max(dp[0][i - 1] , nums1[0] * nums2[i]);
}
for (int i = 1; i < len1; i++)
{
for (int j = 1; j < len2; j++)
{
dp[i][j] = Math.max(dp[i - 1][j] , Math.max(dp[i][j - 1], Math.max(0,dp[i - 1][j - 1]) + nums1[i] * nums2[j]));//max里的max因为非空,所以dp[i-1][j-1]如果为0,可以抛弃
}
}
return dp[len1 - 1][len2 - 1];
}
}