这算是我第一次正式参加 LeetCode 的周赛吧。经过两道题。意料之中(经过上次模拟能够看出来)。总的来讲,脑壳仍是不太灵光。想的有点慢。全球第一名 0:10:19 就所有经过。。。感受个人智商被狠狠的摁在地上摩擦了。java
参考:huntersjmweb
我第一次提交的直接 TLE。而后就没有而后了。数组
TLE 代码的思路(能够不看):svg
int
型的 notParesNum
保存字母个数为奇数的字母的数量。[left, right]
字串取出,统计里面每种字母的个数,若是个数是奇数,那么将 notParesNum
数量加 1。notParesNum / 2
与 k
的关系。若是是大于,那么就是 false
,不然就是 true
。改进一次后的思路:编码
notParesNum / 2
与 k
的关系。若是是 false
,直接 continue
。依然超时了。而后就没时间了,我就没想了。spa
正确思路:code
int
型二维数组 charNum[length + 1][26]
。其中 length
为字符串 s
的长度。而且 charNum[0]
不保存数据。k
的值,若是大于等于 25,那么必定能够将子串替换成回文串,由于最多 26 种字母。(不超时的关键点)k
,若是不超过,那么必定能够将子串替换成回文串。(次关键点)charNum[right]
和 charNum[left]
的差值,统计字母个数为奇数的字母个数 notParesNum
。
notParesNum / 2
与 k
的关系。若是是大于,那么就是 false
,不然就是 true
。运算符优先级从高到低顺序:+ -
,<< >>
,< > <= >=
,||
,=
xml
代码以下:blog
class Solution { public List<Boolean> canMakePaliQueries(String s, int[][] queries) { // 一、预处理,统计每种字母的个数 int length = s.length();// 字母个数 int[][] charNum = new int[length + 1][26];// 保存个数 char[] arrS = s.toCharArray(); for (int i = 0; i < length; ++i) { int ch = arrS[i] - 'a'; charNum[i + 1] = Arrays.copyOf(charNum[i], 26);// 其它字母个数相同 ++charNum[i + 1][ch];// 字母arrS[i]个数加 1 } // 二、保存结果 List<Boolean> ans = new ArrayList<>(); // 三、检测每一个子串是否能够变成回文串 for (int[] querie : queries) { int left = querie[0]; int right = querie[1]; int k = querie[2]; // 26个字母,最多25次就能替换成回文串,或者子串长度的一半不超过k if (k >= 25 || (right - left + 1) >> 1 <= k) { ans.add(true);// 必定能用不超过k次替换就能变成回文串 continue; } // 超过k次的话,就检查非成对字母的个数的一半是否超过k int notParesNum = 0;// 非成对字母个数 int ch = arrS[left] - 'a';// 左边界字母 // 统计子串中每一个字母的个数,若是个数为奇数,notParesNum加1 for (int i = 0; i < 26; ++i) { // 因为是从charNum[1]开始保存数据,故下标要加1 int num = charNum[right + 1][i] - charNum[left + 1][i]; if (i == ch) {// i是左边界字母 ++num;// 个数加1,由于上一步计算差值的时候没有加上这一个 } if (0 != (num & 1)) {// 当前字母个数为奇数 ++notParesNum;// 非对称字母个数加1 } } // 非对称的字母能够经过改变变成同一字母,故除以2 if (notParesNum >> 1 > k) {// 替换次数超过k次 ans.add(false); } else {// 替换次数不超过k次 ans.add(true); } } return ans;// 返回结果 } }
提交结果:
token
什么题目,一直超时超时。参考了别人的代码,用它的代码提交了 七、8 次,只有一次经过了。。就一句话解释算了。
用 int
型数保存字符串的字母状况,低 26 位,每一位保存对应位的字母是否存在,1 表示存在,0 表示不存在。
运算符优先级从高到低顺序:+ -
,<< >>
,==
,&
,|
,|=
。
代码以下:
class Solution { public List<Integer> findNumOfValidWords( String[] words, String[] puzzles) { int[] codeWords = new int[words.length];// 保存编码后的值 for (int i = 0; i < words.length; ++i) { codeWords[i] = code(words[i]);// 给每一个单词编码 } List<Integer> ans = new ArrayList<>(); for (String puzzle : puzzles) {// 遍历全部谜面 int codePuzzle = code(puzzle);// 给谜面编码 int count = 0;// 谜底个数 for (int value : codeWords) {// 遍历全部单词的编码 if ((codePuzzle & value) == value) {// 单词中字母全都在谜面中 if ((value >> puzzle.charAt(0) - 'a' & 1) == 1) { ++count;// 单词包含谜面首字母,谜底个数加1 } } } ans.add(count);// 个数添加到结果中 } return ans;// 返回结果 } // 整数的低26位保存字符串的字母信息,包含字母,对应位置1 private int code(String str) {// 将字符串编码成整数 int num = 0; int length = str.length(); for (int i = 0; i < length; ++i) { num |= 1 << str.charAt(i) - 'a'; } return num;// 返回编码后的值,低26位,每一位表明一个字母 } }
提交结果: