Golang每日一练(leetDay0107) 去除重复字母、最大单词长度乘积

简介: Golang每日一练(leetDay0107) 去除重复字母、最大单词长度乘积

316. 去除重复字母 Remove Duplicate Letters

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

示例 1:

输入:s = "bcabc"

输出:"abc"


示例 2:

输入:s = "cbacdcbc"

输出:"acdb"


提示:

  • 1 <= s.length <= 10^4
  • s 由小写英文字母组成

代码1:贪心算法

package main
import "fmt"
func removeDuplicateLetters(s string) string {
  stack := []byte{}
  count := [26]int{}
  visited := [26]bool{}
  for i := 0; i < len(s); i++ {
    count[s[i]-'a']++
  }
  for i := 0; i < len(s); i++ {
    count[s[i]-'a']--
    if visited[s[i]-'a'] {
      continue
    }
    for len(stack) > 0 && stack[len(stack)-1] > s[i] && count[stack[len(stack)-1]-'a'] > 0 {
      visited[stack[len(stack)-1]-'a'] = false
      stack = stack[:len(stack)-1]
    }
    stack = append(stack, s[i])
    visited[s[i]-'a'] = true
  }
  return string(stack)
}
func main() {
  s := "bcabc"
  fmt.Println(removeDuplicateLetters(s))
  s = "cbacdcbc"
  fmt.Println(removeDuplicateLetters(s))
}

代码2:暴力枚举

package main
import "fmt"
func removeDuplicateLetters(s string) string {
    lastPos := [26]int{}
    for i := 0; i < len(s); i++ {
        lastPos[s[i]-'a'] = i
    }
    visited := [26]bool{}
    res := []byte{}
    for i := 0; i < len(s); i++ {
        if visited[s[i]-'a'] {
            continue
        }
        for len(res) > 0 && res[len(res)-1] > s[i] && lastPos[res[len(res)-1]-'a'] > i {
            visited[res[len(res)-1]-'a'] = false
            res = res[:len(res)-1]
        }
        res = append(res, s[i])
        visited[s[i]-'a'] = true
    }
    return string(res)
}
func main() {
  s := "bcabc"
  fmt.Println(removeDuplicateLetters(s))
  s = "cbacdcbc"
  fmt.Println(removeDuplicateLetters(s))
}

输出:

abc

acdb


318. 最大单词长度乘积 Maximum-product-of-word-lengths

给你一个字符串数组 words ,找出并返回 length(words[i]) * length(words[j]) 的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回 0

示例 1:

输入:words = ["abcw","baz","foo","bar","xtfn","abcdef"]

输出:16

解释这两个单词为 "abcw", "xtfn"。


示例 2:

输入:words = ["a","ab","abc","d","cd","bcd","abcd"]

输出:4

解释这两个单词为 "ab", "cd"。

示例 3:

输入:words = ["a","aa","aaa","aaaa"]

输出:0

解释不存在这样的两个单词。


提示:

  • 2 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] 仅包含小写字母

代码1:位运算 + 哈希表

package main
import "fmt"
func maxProduct(words []string) int {
  n := len(words)
  max := func(x, y int) int {
    if x > y {
      return x
    }
    return y
  }
  hash := make(map[int]int, n)
  for _, word := range words {
    mask := 0
    for _, ch := range word {
      mask |= 1 << (uint)(ch-'a')
    }
    hash[mask] = max(hash[mask], len(word))
  }
  res := 0
  for mask1, len1 := range hash {
    for mask2, len2 := range hash {
      if mask1&mask2 == 0 {
        res = max(res, len1*len2)
      }
    }
  }
  return res
}
func main() {
  words := []string{"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}
  fmt.Println(maxProduct(words))
  words = []string{"a", "ab", "abc", "d", "cd", "bcd", "abcd"}
  fmt.Println(maxProduct(words))
  words = []string{"a", "aa", "aaa", "aaaa"}
  fmt.Println(maxProduct(words))
}

代码2:暴力枚举

package main
import "fmt"
func maxProduct(words []string) int {
    n := len(words)
    res := 0
    for i := 0; i < n; i++ {
        for j := i + 1; j < n; j++ {
            if hasNoCommonChar(words[i], words[j]) {
                res = max(res, len(words[i])*len(words[j]))
            }
        }
    }
    return res
}
func hasNoCommonChar(word1, word2 string) bool {
    for i := 0; i < len(word1); i++ {
        for j := 0; j < len(word2); j++ {
            if word1[i] == word2[j] {
                return false
            }
        }
    }
    return true
}
func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}
func main() {
  words := []string{"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}
  fmt.Println(maxProduct(words))
  words = []string{"a", "ab", "abc", "d", "cd", "bcd", "abcd"}
  fmt.Println(maxProduct(words))
  words = []string{"a", "aa", "aaa", "aaaa"}
  fmt.Println(maxProduct(words))
}

输出:

16

4

0


Go1.21 新增 min、max 内置函数,示例如下:

var x, y int
m := min(x)                 // m == x
m := min(x, y)              // m 是 x 和 y 中较小的那个
m := max(x, y, 10)          // m 是 x 和 y 中较大的一个,但至少是10
c := max(1, 2.0, 10)        // c == 10.0(浮点类型)
f := max(0, float32(x))     // f 的类型是 float32
var s []string
_ = min(s...)               // 无效:不允许使用 slice 参数
t := max("", "foo", "bar")  // t == "foo" (string 类型)

升级到V1.21后,不再需要每次用到max, min就要自定义。

对于一些特殊值和清空,例如:浮点参数、负零、NaN和无穷大。min、max 函数结果适用以下规则:

   x        y    min(x, y)    max(x, y)

 -0.0    0.0       -0.0          0.0  

 -Inf      y         -Inf            y    

 +Inf      y           y         +Inf    

  NaN    y        NaN       NaN

第一行:负零比(非负)零小。

第二行:负无穷大比任何其他数字都小。

第三行:正无穷大于任何其他数字。

第四行:如果有任何一个参数是 NaN,结果就是 NaN。


🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力!

🌟 收藏,你的青睐是我努力的方向!

评论,你的意见是我进步的财富!  

主页:https://hannyang.blog.csdn.net/

Rust每日一练 专栏

(2023.5.16~)更新中...

Golang每日一练 专栏

(2023.3.11~)更新中...

Python每日一练 专栏

(2023.2.18~2023.5.18)暂停更

C/C++每日一练 专栏

(2023.2.18~2023.5.18)暂停更

Java每日一练 专栏

(2023.3.11~2023.5.18)暂停更


目录
相关文章
|
1月前
|
Shell Linux 算法
Shell编程——弱数据类型的脚本语言快速入门指南
Shell编程——弱数据类型的脚本语言快速入门指南
62 0
Shell编程——弱数据类型的脚本语言快速入门指南
|
1月前
|
Go Linux Shell
Linux 终端命令之文件浏览(2) more
Linux 终端命令之文件浏览(2) more
40 0
Linux 终端命令之文件浏览(2) more
|
1月前
|
Shell 机器学习/深度学习 Linux
Linux 终端操作命令(2)内部命令
Linux 终端操作命令(2)内部命令
32 0
Linux 终端操作命令(2)内部命令
|
1月前
|
C++ 算法 存储
力扣 C++|一题多解之动态规划专题(2)
力扣 C++|一题多解之动态规划专题(2)
44 0
力扣 C++|一题多解之动态规划专题(2)
|
1月前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
123 0
|
1月前
|
前端开发 Go
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
【5月更文挑战第3天】Go语言通过goroutines和channels实现异步编程,虽无内置Future/Promise,但可借助其特性模拟。本文探讨了如何使用channel实现Future模式,提供了异步获取URL内容长度的示例,并警示了Channel泄漏、错误处理和并发控制等常见问题。为避免这些问题,建议显式关闭channel、使用context.Context、并发控制机制及有效传播错误。理解并应用这些技巧能提升Go语言异步编程的效率和健壮性。
67 5
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
|
1月前
|
Prometheus 监控 Cloud Native
Golang深入浅出之-Go语言中的分布式追踪与监控系统集成
【5月更文挑战第4天】本文探讨了Go语言中分布式追踪与监控的重要性,包括追踪的三个核心组件和监控系统集成。常见问题有追踪数据丢失、性能开销和监控指标不当。解决策略涉及使用OpenTracing或OpenTelemetry协议、采样策略以及聚焦关键指标。文中提供了OpenTelemetry和Prometheus的Go代码示例,强调全面可观测性对微服务架构的意义,并提示选择合适工具和策略以确保系统稳定高效。
166 5
|
1月前
|
监控 负载均衡 算法
Golang深入浅出之-Go语言中的协程池设计与实现
【5月更文挑战第3天】本文探讨了Go语言中的协程池设计,用于管理goroutine并优化并发性能。协程池通过限制同时运行的goroutine数量防止资源耗尽,包括任务队列和工作协程两部分。基本实现思路涉及使用channel作为任务队列,固定数量的工作协程处理任务。文章还列举了一个简单的协程池实现示例,并讨论了常见问题如任务队列溢出、协程泄露和任务调度不均,提出了解决方案。通过合理设置缓冲区大小、确保资源释放、优化任务调度以及监控与调试,可以避免这些问题,提升系统性能和稳定性。
65 6
|
1月前
|
负载均衡 算法 Go
Golang深入浅出之-Go语言中的服务注册与发现机制
【5月更文挑战第4天】本文探讨了Go语言中服务注册与发现的关键原理和实践,包括服务注册、心跳机制、一致性问题和负载均衡策略。示例代码演示了使用Consul进行服务注册和客户端发现服务的实现。在实际应用中,需要解决心跳失效、注册信息一致性和服务负载均衡等问题,以确保微服务架构的稳定性和效率。
37 3
|
1月前
|
安全 Go
Golang深入浅出之-Go语言中的并发安全队列:实现与应用
【5月更文挑战第3天】本文探讨了Go语言中的并发安全队列,它是构建高性能并发系统的基础。文章介绍了两种实现方法:1) 使用`sync.Mutex`保护的简单队列,通过加锁解锁确保数据一致性;2) 使用通道(Channel)实现无锁队列,天生并发安全。同时,文中列举了并发编程中常见的死锁、数据竞争和通道阻塞问题,并给出了避免这些问题的策略,如明确锁边界、使用带缓冲通道、优雅处理关闭以及利用Go标准库。
42 5