diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 7b8aa28..ec65b43 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -23231,3 +23231,100 @@ private: }; ``` +## day344 2025-02-17 +### 1079. Letter Tile Possibilities +You have n tiles, where each tile has one letter tiles[i] printed on it. + +Return the number of possible non-empty sequences of letters you can make using the letters printed on those tiles. + +![0217yNgcl5KkXGHp](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0217yNgcl5KkXGHp.png) + +### 题解 +本题的目标即为找到这些字母构成的全部可能组合的个数,因此是经典的可以利用回溯法的场景,但要注意对每个位置遍历可行的字母时对同一个字母仅需遍历一遍,即使该字母有多个,因为只要放在该位置的是同一个字母得到的就会是同一个组合,其对后续继续构建字符串没有影响,考虑ABABA这样的字符串,三个字母A彼此无论怎样交换位置,得到的都还是同一个字符串。 +则在算法过程中,先统计给定字符串中各个字母的个数放在哈希表中。每当继续放置下一个位置的字母时,遍历当前剩余的可用非重复字母并依次放置在该位置上,将该字母的个数减一,若字母个数为0则从哈希表中移除,每当遍历过程中放置了一个字母均将结果加1,最终即可统计出全部的字符串个数。 + +### 代码 +```cpp +class Solution { +public: + int numTilePossibilities(std::string tiles) { + unordered_map counts; + for (char tile : tiles) { + counts[tile]++; + } + + return backtrack(counts); + } + +private: + int backtrack(unordered_map& counts) { + int total_sequences = 0; + + for (auto& [tile, count] : counts) { + if (count > 0) { + total_sequences++; + count--; + total_sequences += backtrack(counts); + count++; + } + } + + return total_sequences; + } +}; +``` +## day345 2025-02-18 +### 2375. Construct Smallest Number From DI String +You are given a 0-indexed string pattern of length n consisting of the characters 'I' meaning increasing and 'D' meaning decreasing. + +A 0-indexed string num of length n + 1 is created using the following conditions: + +num consists of the digits '1' to '9', where each digit is used at most once. +If pattern\[i] == 'I', then num\[i] < num\[i + 1]. +If pattern\[i] == 'D', then num\[i] > num\[i + 1]. +Return the lexicographically smallest possible string num that meets the conditions. + +![0218bs1xs6VEV2Nd](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0218bs1xs6VEV2Nd.png) + +### 题解 +本题考虑数组遍历时只能向一个方向遍历,如果从前向后遍历则无法预知后面要给几个D预留出足够大小的数字,即无法拿到后面的关键信息,因此需要遍历两次来获取完整的信息,第一次从后向前遍历,记录连续出现的D的个数,当遇到I时将D的个数赋值给对应位置并将记录的个数清零,这样相当于通知当在这个位置增加数字大小时要提前预留出后面的D个数的大小空间。 + +再正向遍历数组,同样也要统计从前一个I到下一个I之间的D的个数m(考虑123546这样的字符串,对于4来说增加的时候不能仅仅加1,还要加上前方减掉的数字大小,因为减掉的这一区间的所有数字已经被使用了,因此我们要恢复到未减数字之前的值并基于此继续向上增加),遇到I时将当前数字加1再增加记录的预留D的个数和m得到下一个值并将m清零。遇到D则将当前数字减一,最终可得满足条件的字符串。因为每次放置数字时都放置了当前位置可能的最小数字,因此这样得到的字符串是字典序最小的 + +### 代码 +```cpp +class Solution { +public: + string smallestNumber(string pattern) { + int len = pattern.size(); + vector reverse(len,0); + int dsum = 0; + for(int i=len-1;i>=0;i--){ + if(pattern[i] == 'D'){ + dsum++; + }else{ + if(dsum > 0){ + reverse[i] = dsum; + dsum = 0; + } + } + } + char current = '1'+dsum; + string result; + result += current; + int addD = 0; + for(int i=0;i