「LeetCode」第 264 场周赛(上)

336 阅读3分钟

这是我参与11月更文挑战的第7天,活动详情查看2021最后一次更文挑战

链接

leetcode-cn.com/contest/wee… 周赛一共四道题,今天先带来前两道题的解析。

题目

2047. 句子中的有效单词数

简单模拟

解析

简单模拟的关键是安排好每个判断语句的顺序,使得用最短的判断逻辑涵盖所有需要判断的情况。往往最简洁的涵盖所有情况的判断语句出错的可能性最低。

在这道题中,首先将每个token分隔开,注意多个空格的情况(使用Python最方便的做法是使用.split()代替.split(' ')然后再判断空token);然后判断token尾是否有标点符号;然后遍历每个字符,如果出现数字或标点即跳出判断;然后使用一个变量判断是否出现连词符、以及连词符的位置是否合法。

代码

class Solution:
    def countValidWords(self, sentence: str) -> int:
        interpunctions = ['!', ',', '.']
        numbers = [chr(ord('0') + i)  for i in range(0, 10)]
        letters = [chr(ord('a') + i)  for i in range(0, 26)]
        tokens = list(filter(lambda word: len(word) > 0, sentence.split(' ')))
        count = 0
        for token in tokens:
            begin, end = 0, len(token)-1 if token[-1] not in interpunctions else len(token) - 2
            isHyphenExist = False
            isTokenValid = True
            p = begin
            while p <= end:
                if token[p] in numbers or token[p] in interpunctions:
                    isTokenValid = False
                    break
                elif token[p] == '-':
                    if isHyphenExist == True or p == begin or p == end or token[p-1] not in letters or token[p+1] not in letters:
                        isTokenValid = False
                        break
                    else:
                        isHyphenExist = True
                p += 1
            if isTokenValid:
                count += 1
        return count

正则

解析

正则的写法很简洁(不知道时间复杂度和O(n)相比怎么样),但是根据题目的要求编写正则耗时,而且很难debug

代码

转载自解法

class Solution:
    def countValidWords(self, sentence: str) -> int:
        res = 0
        for word in sentence.split() :
            if re.match("[a-z]*([a-z]-[a-z])?[a-z]*[!,.]?$", word) : res += 1
        return res

2048. 下一个更大的数值平衡数

暴力枚举(打表)

解析

在周赛中,因为看到数值范围只到10^6,所以我想将符合情况的数字都列了出来。但是由于没考虑完全列漏了,所以罚时了不少时间。(由于1、22、333这六个数字混合的情况很难写,所以还特意写了个循环转一下数字)

代码

class Solution:
    def __init__(self):
        self.ansList = [1, 22, 122, 212, 221, 333, 1333, 3133, 3313, 3331, 4444, 14444, 41444, 44144, 44414, 44441, 55555, 155555, 515555, 551555, 555155, 555515, 555551, 22333, 23233, 23323, 23332, 32233, 32323, 32332, 33223, 33232, 33322, 224444, 242444, 244244, 244424, 244442, 422444, 424244, 424424, 424442, 442244, 442424, 442442, 444224, 444242, 444422, 666666]
        extras = [22333, 23233, 23323, 23332, 32233, 32323, 32332, 33223, 33232, 33322]
        for i in range(0, 6):
            for num in extras:
                strList = list(str(num))
                strList.insert(i, '1')
                strNum = ''.join(strList)
                self.ansList.append(int(strNum))
        self.ansList.sort()
        self.maxAns = 1224444

    def nextBeautifulNumber(self, n: int) -> int:
        for ans in self.ansList:
            if n < ans:
                return ans
        return self.maxAns

改进

打表后的查找过程使用二分

回溯打表

解析

确定能组成数值平衡树的成分(比如1个1、2个2和3个3,2个2和4个4等),回溯出所有的数值平衡树然后二分查找

代码

绯笑解答

class Solution {
    public int nextBeautifulNumber(int n) {
        Map<Integer,int[][]> map = new HashMap<>();
        map.put(3,new int[][]{{1,2,2}});
        map.put(4,new int[][]{{1,3,3,3}});
        map.put(5,new int[][]{{1,4,4,4,4},{2,2,3,3,3}});
        map.put(6,new int[][]{{1,2,2,3,3,3},{1,5,5,5,5,5},{2,2,4,4,4,4}});
        int[][] enr = {{1,1},{22,22},{333,122},{4444,1333},{55555,14444},{666666,122333},{7777777,1224444}};
        int len = String.valueOf(n).length();
        if(len == 7) return enr[len-1][1];
        if(n >= enr[len-1][0]) return enr[len][1];
        if(n == 0) return 1;
        if(n < 100) return 22;
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        for(int[] arr : map.get(len)){
            backtrack(pq,arr,new boolean[arr.length],0,0,len,n,0);
        }
        return pq.isEmpty() ? enr[len-1][0] : pq.poll();
    }
    private void backtrack(PriorityQueue<Integer> pq,int[] arr,boolean[] flag,int num,int cont,int len ,int n ,int j){
        if(cont == len && num > n){
            pq.add(num);
        }else{
            for(int i=0; i<arr.length; i++){
                if(flag[i]) continue;
                num = num*10 + arr[i];
                cont++;
                flag[i] = true;
                backtrack(pq,arr,flag,num,cont,len,n,j);
                num = num/10;
                cont--;
                flag[i] = false;
            }
        }
    }
}

暴力查找

解析

每次+1往上枚举,看+1的结果是否符合数值平衡数的要求。

代码

灵茶山艾府解答

func nextBeautifulNumber(n int) int {
next:
	for n++; ; n++ {
		cnt := [10]int{}
		for x := n; x > 0; x /= 10 {
			cnt[x%10]++
		}
		for x := n; x > 0; x /= 10 {
			if cnt[x%10] != x%10 {
				continue next
			}
		}
		return n
	}
}

改进

在上述判断基础上判断0、7、8、9数字的出现,出现即跳出循环