- 写一个函数,接收一个字符串参数,返回字符串中第一个只出现一次的字符。例如,输入"abacddbe",返回"c"。
- 实现一个并发安全的计数器,要求支持以下三个方法:
Increment():将计数器加1。Decrement():将计数器减1。GetValue():获取当前计数器的值。
- 给定一个整数切片,编写一个函数,将其中的所有重复元素移除,并返回新的切片。要求保持原有元素的顺序不变。例如,输入[1, 2, 3, 2, 4, 1],返回[1, 2, 3, 4]。
- 实现一个LRU(最近最少使用)缓存机制,要求支持以下两个操作:
Get(key string) (value string, ok bool):根据给定的键获取对应的值,如果键不存在,则返回空字符串和false。Set(key string, value string):将给定的键值对添加到缓存中,如果缓存已满,则删除最近最少使用的键值对。
- 编写一个函数,接收一个字符串切片,将其中的字符串按照字符的长度从小到大进行排序。如果两个字符串长度相同,则按照字典序进行排序。例如,输入["go", "python", "java", "ruby"],返回["go", "java", "ruby", "python"]。
1. 写一个函数,接收一个字符串参数,返回字符串中第一个只出现一次的字符。例如,输入"abacddbe",返回"c"。
以下是一个实现函数的示例,该函数接收一个字符串参数,并返回字符串中第一个只出现一次的字符:
func firstUniqueChar(str string) string {
charCount := make(map[rune]int)
// 统计字符出现的次数
for _, ch := range str {
charCount[ch]++
}
// 遍历字符串找到第一个只出现一次的字符
for _, ch := range str {
if charCount[ch] == 1 {
return string(ch)
}
}
return "" // 没有只出现一次的字符
}
func main() {
str := "abacddbe"
result := firstUniqueChar(str)
fmt.Println(result) // 输出: "c"
}
在上述示例中,我们首先使用 charCount 哈希表统计字符串中每个字符出现的次数。然后,我们遍历字符串,找到第一个只出现一次的字符,并将其作为结果返回。
在主函数中,我们调用 firstUniqueChar 函数,并将字符串 "abacddbe" 作为参数传递。最后,输出结果为 "c"。
请注意,上述示例中的实现是基于 Unicode 字符集的。如果你的应用程序中使用的是其他字符集,可以相应地进行调整。此外,该实现假设输入字符串非空,如果输入为空字符串,可以根据需要进行额外处理。
2. 实现一个并发安全的计数器,要求支持以下三个方法:
* `Increment()`:将计数器加1。
* `Decrement()`:将计数器减1**。**
* `GetValue()`:获取当前计数器的值。
下面是一个并发安全的计数器的实现,支持 Increment()、Decrement() 和 GetValue() 三个方法:
import "sync"
type Counter struct {
value int
mutex sync.Mutex
}
func NewCounter() *Counter {
return &Counter{}
}
func (c *Counter) Increment() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.value++
}
func (c *Counter) Decrement() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.value--
}
func (c *Counter) GetValue() int {
c.mutex.Lock()
defer c.mutex.Unlock()
return c.value
}
在上述代码中,Counter 结构体包含一个整数字段 value 表示计数器的值,以及一个互斥锁 mutex 用于保护计数器的并发访问。
NewCounter() 函数用于创建一个新的计数器实例。
Increment() 方法使用互斥锁对计数器的值加1。
Decrement() 方法使用互斥锁对计数器的值减1。
GetValue() 方法使用互斥锁获取当前计数器的值。
通过使用互斥锁,可以确保多个 goroutine 对计数器的并发访问是安全的,避免了竞态条件和数据不一致的问题。
3. 给定一个整数切片,编写一个函数,将其中的所有重复元素移除,并返回新的切片。要求保持原有元素的顺序不变。例如,输入[1, 2, 3, 2, 4, 1],返回[1, 2, 3, 4]。
下面是一个移除整数切片中重复元素的函数实现:
func RemoveDuplicates(nums []int) []int {
seen := make(map[int]bool)
result := []int{}
for _, num := range nums {
if !seen[num] {
result = append(result, num)
seen[num] = true
}
}
return result
}
在上述代码中,我们使用一个 seen 哈希表来记录已经出现过的元素。然后,我们遍历输入的整数切片 nums,如果当前元素 num 在 seen 中不存在,则将其添加到结果切片 result 中,并将 seen[num] 设置为 true 表示已经见过该元素。
最后,返回结果切片 result,其中包含了所有不重复的元素,并保持了原有的顺序。
你可以调用 RemoveDuplicates 函数,并传入一个整数切片作为参数进行测试。例如:
func main() {
nums := []int{1, 2, 3, 2, 4, 1}
result := RemoveDuplicates(nums)
fmt.Println(result) // 输出: [1 2 3 4]
}
上述示例会打印出 [1 2 3 4],表示重复元素已被移除,只保留了不重复的元素。
4. 实现一个LRU(最近最少使用)缓存机制,要求支持以下两个操作:
* `Get(key string) (value string, ok bool)`:根据给定的键获取对应的值,如果键不存在,则返回空字符串和false。
* `Set(key string, value string)`:将给定的键值对添加到缓存中,如果缓存已满,则删除最近最少使用的键值对。
下面是一个基于哈希表和双向链表的 LRU 缓存实现:
import (
"container/list"
"fmt"
)
type LRUCache struct {
capacity int
cache map[string]*list.Element
lruList *list.List
}
type CacheItem struct {
key string
value string
}
func NewLRUCache(capacity int) *LRUCache {
return &LRUCache{
capacity: capacity,
cache: make(map[string]*list.Element),
lruList: list.New(),
}
}
func (lru *LRUCache) Get(key string) (string, bool) {
if ele, ok := lru.cache[key]; ok {
lru.lruList.MoveToFront(ele)
return ele.Value.(*CacheItem).value, true
}
return "", false
}
func (lru *LRUCache) Set(key string, value string) {
if ele, ok := lru.cache[key]; ok {
ele.Value.(*CacheItem).value = value
lru.lruList.MoveToFront(ele)
} else {
if len(lru.cache) >= lru.capacity {
// 淘汰最近最少使用的缓存项
back := lru.lruList.Back()
delete(lru.cache, back.Value.(*CacheItem).key)
lru.lruList.Remove(back)
}
newItem := &CacheItem{key, value}
newEle := lru.lruList.PushFront(newItem)
lru.cache[key] = newEle
}
}
func main() {
cache := NewLRUCache(2)
cache.Set("key1", "value1")
cache.Set("key2", "value2")
fmt.Println(cache.Get("key1")) // 输出: value1
cache.Set("key3", "value3")
fmt.Println(cache.Get("key2")) // 输出: ""
cache.Set("key4", "value4")
fmt.Println(cache.Get("key1")) // 输出: ""
fmt.Println(cache.Get("key3")) // 输出: value3
fmt.Println(cache.Get("key4")) // 输出: value4
}
在上述代码中,LRUCache 结构体包含一个容量字段 capacity,一个哈希表 cache 用于快速查找缓存项,以及一个双向链表 lruList 用于存储缓存项的访问顺序。
Get 方法根据给定的键获取对应的值,并将访问过的缓存项移动到链表头部表示最近使用。
Set 方法插入或更新缓存项,并在缓存已满时淘汰最近最少使用的缓存项。
在 main 函数中,我们创建了一个容量为 2 的 LRU 缓存,并进行了一系列操作和输出。你可以根据需要修改示例代码,观察 LRU 缓存的行为。
注意:上述示例是一种简单的实现方式,适用于单线程环境。在并发环境下,需要增加适当的同步机制来保证线程安全。
5. 编写一个函数,接收一个字符串切片,将其中的字符串按照字符的长度从小到大进行排序。
如果两个字符串长度相同,则按照字典序进行排序。例如,输入["go", "python", "java", "ruby"],返回["go", "java", "ruby", "python"]。
以下是一个按照字符串长度从小到大排序的函数实现:
import (
"sort"
)
func SortStringsByLength(strs []string) []string {
sort.Slice(strs, func(i, j int) bool {
if len(strs[i]) != len(strs[j]) {
return len(strs[i]) < len(strs[j])
}
return strs[i] < strs[j]
})
return strs
}
在上述代码中,我们使用 sort.Slice 函数进行排序,传入一个比较函数作为参数。比较函数根据字符串的长度和字典序进行排序。
如果两个字符串的长度不同,则按照长度从小到大进行排序。
如果两个字符串的长度相同,则按照字典序进行排序。
最后,返回排序后的字符串切片 strs。
你可以调用 SortStringsByLength 函数,并传入一个字符串切片作为参数进行测试。例如:
func main() {
strs := []string{"go", "python", "java", "ruby"}
result := SortStringsByLength(strs)
fmt.Println(result) // 输出: [go java ruby python]
}
上述示例会打印出 ["go", "java", "ruby", "python"],表示字符串已按照长度从小到大进行排序,如果长度相同,则按照字典序排序。