From bdfbea408d5940324a7a62f187f639bd2a92a501 Mon Sep 17 00:00:00 2001 From: gameloader Date: Thu, 6 Jun 2024 14:00:15 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 202 +++++++++++++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 3 deletions(-) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 4f62485..6a27e86 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -6759,7 +6759,9 @@ func reverseString(s []byte) { ``` ## day98 2024-06-03 -### 2486. Append Characters to String to Make subsequence + +### 2486. Append Characters to String to Make subsequence + You are given two strings s and t consisting of only lowercase English letters. Return the minimum number of characters that need to be appended to the end of s so that t becomes a subsequence of s. @@ -6786,7 +6788,7 @@ Input: s = "z", t = "abcde" Output: 5 Explanation: Append the characters "abcde" to the end of s so that s = "zabcde". Now, t is a subsequence of s ("zabcde"). -It can be shown that appending any 4 characters to the end of s will never make t a subsequence. +It can be shown that appending any 4 characters to the end of s will never make t a subsequence. ### 题解 @@ -6794,7 +6796,7 @@ It can be shown that appending any 4 characters to the end of s will never make ### 代码 -```go +```go func appendCharacters(s string, t string) int { prefix := 0 tlen := len(t) @@ -6807,3 +6809,197 @@ func appendCharacters(s string, t string) int { return tlen-prefix } ``` + +## day99 2024-06-04 + +### 409. Longest Palindrome + +Given a string s which consists of lowercase or uppercase letters, return the length of the longest +palindrome +that can be built with those letters. + +Letters are case sensitive, for example, "Aa" is not considered a palindrome. + +![0604VbbEvdynF0Yj](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0604VbbEvdynF0Yj.png) + +### 题解 + +本题也是一道简单题, 最近几天的每日一题都比较简单, 因为是能组成的最长回文串, 与顺序无关, 因此只需统计字母个数即可. 遍历字符串并统计字母, 每当同一个字母有两个时就将结果加2并将字母个数重置为0. 遍历一遍后如果仍有字母剩余1个,则将结果加1表示奇数长度的回文串在中间添加的字母. + +先统计全部字母的数量再最终求和会快一些, 减少了不必要的判断和加法操作. + +### 代码 + +```go +func longestPalindrome(s string) int { + charslice := make([]int,52) + for i,_ := range s{ + if s[i] >= 'a'{ + charslice[s[i]-'a']++ + }else{ + charslice[26+s[i]-'A']++ + } + } + result := 0 + odd := 0 + for _,num := range charslice{ + if num % 2 == 0{ + result += num + }else{ + result += num - 1 + odd = 1 + } + } + return result + odd +} + +``` + +## day100 2024-06-05 + +### 1002. Find Common Characters + +Given a string array words, return an array of all characters that show up in all strings within the words (including duplicates). You may return the answer in any order. + +![0605COPNsAMdo0fH](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0605COPNsAMdo0fH.png) + +### 题解 + +本题也是一道简单题, 仍然是寻找在所有单词中都存在的字母, 重复的字母单独计算, 同样不要求顺序, 对于没有顺序要求的字符串问题, 计数往往是很好的解决方法, 因此只需依次遍历所有单词, 对单词中所有字母计数, 再与之前的字母计数比较, 取二者之间的较小值, 最后根据每个字母的计数个数输出答案即可. 注意题目限制字符串长度最多为100, 因此初始化为101保存字母个数的数组即可正常被更小的值刷新. + +### 代码 + +```go +func commonChars(words []string) []string { + beforechars := []int{101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101} + for _,word := range words{ + nowchars := make([]int,26) + for i,_ := range word{ + nowchars[word[i]-'a']++ + } + for i,value := range nowchars{ + beforechars[i] = min(beforechars[i],value) + } + } + fmt.Println(beforechars) + result := []string{} + for i,chars := range beforechars{ + if chars > 0{ + for chars>0{ + result = append(result, string('a'+i)) + chars-- + } + } + } + return result +} +``` + +## day101 2024-06-06 + +### 846. Hand of Straights + +Alice has some number of cards and she wants to rearrange the cards into groups so that each group is of size groupSize, and consists of groupSize consecutive cards. + +Given an integer array hand where hand[i] is the value written on the ith card and an integer groupSize, return true if she can rearrange the cards, or false otherwise. + +![0606YDapQlDOY3WG](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0606YDapQlDOY3WG.png) + +### 题解 + +因为要将数组中的数分为几组连续相邻的数且组内个数为groupSize大小, 显然每次都扫描整个数组寻找当前数字的下一个相邻数字效率极低, 所以可以先排序, 排序后数组中的数从小到大排列, 如果相邻的数存在应该在数组中是相邻的, 因此从头遍历排序后的数组, 依次将相邻的数放入一个groupSize大小的判别数组中并在数组中删掉放入的数, 遇到相同的数先继续向后遍历寻找下一个不同的相邻数字, 直到填满整个判别数组为止, 如果找不到相邻的数则可直接返回false. 填满判别数组后再从头遍历数组, 清空判别数组, 重复上述操作. 直到数组中没有数且判别数组刚好填满为止. + +### 代码 + +```go +func isNStraightHand(hand []int, groupSize int) bool { + sort.Ints(hand) + arrangelen := 0 + current := 0 + for len(hand) > 0{ + arrangelen = 0 + remaingroup := []int{} + current = hand[0] + for _, value := range hand{ + if current == value && arrangelen < groupSize{ + arrangelen++ + hand = hand[1:] + current++ + + }else if arrangelen == groupSize{ + break + }else{ + if value == current - 1{ + hand = hand[1:] + remaingroup = append(remaingroup, value) + }else{ + return false + } + } + } + hand = append(remaingroup, hand...) + } + if arrangelen == groupSize{ + return true + }else{ + return false + } +} + +``` + +### 总结 + +这种算法是可行的, 但由于大量的数组删除元素和数组连接操作, 使得实际耗时比较长. 本题还可以使用优先级队列(最小堆)来求解, 将元素全部放入最小堆中, 构造一个哈希表, 保存每个元素和其对应的元素个数. 每次从堆顶弹出一个元素, 即当前的最小元素, 如果弹出的元素不是相邻的数, 则返回false, 弹出后减少该元素在哈希表中对应的元素个数, 直到为0判断其前面是否还有其他更小的数, 如果有可直接返回false(这种情况下一定无法在group中再构成连续相邻的数了). 在函数开头可以先判断下数组的长度能否被groupSize整除, 不能直接返回false, 后面就可以不用再判断是否能填满最后一个group了. 开头的这个判断通过一些简单的方法过滤掉了不满足条件的解, 避免后续浪费时间对这些解进行判断, 做题时要先考虑一些这样可以通过简单判断排除不可行解的情况. 可以大大加快整体的运行效率. + +```go +type MinHeap []int + +func (h MinHeap) Len() int { return len(h) } +func (h MinHeap) Less(i, j int) bool { return h[i] < h[j] } +func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *MinHeap) Push(x interface{}) { + *h = append(*h, x.(int)) +} + +func (h *MinHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} + +func isNStraightHand(hand []int, groupSize int) bool { + if len(hand) % groupSize != 0 { + return false + } + h := MinHeap{} + heap.Init(&h) + hm := make(map[int]int) + for _, elem := range hand { + hm[elem]++ + } + for key, _ := range hm { + heap.Push(&h,key) + } + for h.Len() > 0 { + startGroup := h[0] + for i := startGroup; i < startGroup + groupSize; i++ { + if _, ok := hm[i]; !ok { + return false + } + hm[i]-- + if hm[i] == 0 { + if i != h[0] { + return false + } + heap.Pop(&h) + } + } + } + return true + +} +```