leetcode update

This commit is contained in:
gameloader 2024-06-06 14:00:15 +08:00
parent 14d2057a8b
commit bdfbea408d

View File

@ -6759,7 +6759,9 @@ func reverseString(s []byte) {
``` ```
## day98 2024-06-03 ## 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. 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. Return the minimum number of characters that need to be appended to the end of s so that t becomes a subsequence of s.
@ -6807,3 +6809,197 @@ func appendCharacters(s string, t string) int {
return tlen-prefix 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
}
```