定长子串中元音的最大数目
给你字符串 s
和整数 k
。
请返回字符串 s
中长度为 k
的单个子字符串中可能包含的最大元音字母数。
英文中的 元音字母 为(a
, e
, i
, o
, u
)。
示例 1:
输入:s = "abciiidef", k = 3 输出:3 解释:子字符串 "iii" 包含 3 个元音字母。
示例 2:
输入:s = "aeiou", k = 2 输出:2 解释:任意长度为 2 的子字符串都包含 2 个元音字母。
示例 3:
输入:s = "leetcode", k = 3 输出:2 解释:"lee"、"eet" 和 "ode" 都包含 2 个元音字母。
示例 4:
输入:s = "rhythms", k = 4 输出:0 解释:字符串 s 中不含任何元音字母。
示例 5:
输入:s = "tryhard", k = 4 输出:1
提示:
1 <= s.length <= 10^5
s
由小写英文字母组成1 <= k <= s.length
// 超时,即使是避免掉重复 y.includes(s[i]), 特殊情况还是超时,明显就是时间复杂度过高问题,但有不知怎么减少
/** * @param {string} s * @param {number} k * @return {number} */ var maxVowels = function(s, k) { let i=0, len = s.length; // let arr = s.split('') let y = ['a', 'e', 'i', 'o', 'u']; let res = 0; let arr = new Array(len).fill(0); for(let i=0; i<len; i++){ if(y.includes(s[i])){ arr[i] = 1 // count++ } } while(i<len-2){ let count = 0; arr.slice(i, i+k).forEach(f=>{ if(f===1){ count++ } }) res = Math.max(res, count) if(res===k){ return k } i++; } // while(i<len-2){ // let count = 0; // if(y.includes(s[i])){ // s.slice(i, i+k).split('').forEach(f=>{ // if(y.includes(f)){ // count++ // } // }) // res = Math.max(res, count) // if(res===k){ // return k // } // // i++; // } // i++; // } return res; };
思路: 很多地方会用数组做一个前面一个和后面一个的关系式子,就像dp那样
记录某个到某个索引处共出现的次数
// 就是之前数组不仅要记录是否是”原因字母“,好要记录,到某个索引处之前共有几个”原因字母“,其实当时也想某个”原因字母“必须知道它前后是不是,是有影响的,我当时会想到有没有最大连续的。
//但是呢,高手用数组记录出现”元音字母“出现的次数。
// 第二个循环,arr[i]=n1, 之后k个每个加1,最大也就是n1+k,所以最大差值也就是k
while(i<=len-k){
res = Math.max(res, arr[i+k]-arr[i]);
i++;
}
/** * @param {string} s * @param {number} k * @return {number} */ var maxVowels = function(s, k) { let t = ['a','e','i','o','u']; let len = s.length; let arr = new Array(len+1).fill(0); for(let i=1; i<=len; i++){ arr[i] = arr[i-1]+(~t.indexOf(s[i-1])?1:0); } console.log(arr) let res = 0; for(let i = k; i <= len; ++ i){ res = Math.max(res, arr[i]-arr[i-k]); } return res };
// 思路:遍历整个字符串的时候,不用截取子字符串,再操作。 // 先计算出第一个子字符串的需要信息,然后遍历,尾部多一个就+1,头部多一个,不操作,双索引操作。 /** * @param {string} s * @param {number} k * @return {number} */ var maxVowels = function(s, k) { let len = s.length; let l = 0, r = k-1; let tmp = 0, ans = 0; let t = ['a','e','i','o','u']; for(let i=l; i<=r; i++){ if(t.includes(s[i])){ tmp++ } } ans =Math.max(ans, tmp); // 必须循环到len-1,因为是从k-1开始的 while(r!=len-1){ r++ if(t.includes(s[r])){ tmp++ } if(t.includes(s[l])){ tmp-- } l++; ans = Math.max(ans, tmp); if(ans === k) return k } return ans };
给你一棵二叉树,每个节点的值为 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] 。
示例 2:
输入:root = [2,1,1,1,3,null,null,null,null,null,1] 输出:1 解释:上图为给定二叉树。总共有 3 条从根到叶子的路径:绿色路径 [2,1,1] ,路径 [2,1,3,1] 和路径 [2,1] 。 这些路径中只有绿色路径是伪回文路径,因为 [2,1,1] 存在回文排列 [1,2,1] 。
示例 3:
输入:root = [9] 输出:1
提示:
- 给定二叉树的节点数目在
1
到10^5
之间。 - 节点值在
1
到9
之间。
// 到达底部,拿到这条路径上的所有节点,然后判断是否是回文,但是这个路径总是深度优先遍历的顺序,所有路径都一样,然后就不知怎么写了 var pseudoPalindromicPaths = function(root) { // let all = []; // const dfs=(node, arr)=>{ // if(!node){ // return; // } // arr.push(node.val); // // if(!node.left && !node.right){ // // all.push(arr); // // return // // } // if(node.left) { // dfs(node.left, arr) // } // if(node.right) { // dfs(node.right, arr) // } // } }
var pseudoPalindromicPaths = function(root) { const check=(cnt)=> { let odd = 0; for(let i = 0; i <= 9; i++) { if(cnt[i]&1) { odd++; } } if(odd <= 1) { return 1; } return 0; } const dfs=(root, cnt)=> { if(!root) { return 0; } cnt[root.val] ++; if(!root.left && !root.right) { // 奇数个数<=1才是伪回文 let anw = check(cnt); // 回溯减去当前值 cnt[root.val]--; console.log('anw: ',anw) return anw; } let anw = 0; if(root.left) { anw += dfs(root.left, cnt); } if(root.right) { anw += dfs(root.right, cnt); } // 回溯减去当前值 cnt[root.val] --; console.log('return anw: ',anw) return anw; } let cnt = new Array(10).fill(0); return dfs(root, cnt); }
class Solution { int ans=0; public int pseudoPalindromicPaths (TreeNode root) { if(root==null) return 0; helper(root,0); return ans; } void helper(TreeNode node,int temp){ temp^=(1<<node.val);//node节点的val为几就左移几位 if(node.left==null&&node.right==null){//判断是否叶子节点 if(temp==0||(temp&(temp-1))==0){//判断是否为伪回文 ans++; } } if(node.left!=null) helper(node.left,temp); if(node.right!=null) helper(node.right,temp); return; } }
作者:rational-irrationality 链接:https://leetcode-cn.com/problems/pseudo-palindromic-paths-in-a-binary-tree/solution/java-dfs-shuang-bai-by-rational-irrationality/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。