叠盘子排序 | 豆包MarsCode AI刷题
一开始我使用队列来做,其实完全没有必要,用两个指针就可以了,记录一下
以及学习了strings.Join的使用,放在文章末尾
问题描述
小M有一个独特的方式来收拾家中的盘子。每次用餐后,他会将盘子按照他们的序号顺序叠放。盘子的序号都是唯一的整数,并且在收拾前就是递增的。小M的叠放规则是,每一堆盘子的序号都是连续递增的,并且至少包含3个盘子。需要编写程序帮助小M确定盘子的叠放方式。
例如,输入的盘子序号是 [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20],按照小M的规则,连续递增序列 -3, -2, -1 可以叠在一起表示为 -3--1,而 18, 19, 20 可以叠在一起表示为 18-20。不满足连续递增至少3个的,如 2, 10, 15, 16 都应单独列出。
输入参数
plates: 一个整数数组,表示盘子的序号。n: 盘子总数。
测试样例
样例1
输入:
plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20]
n = 10
输出:
"-3--1,2,10,15,16,18-20"
样例2
输入:
plates = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
n = 20
输出:
"-6,-3-1,3-5,7-11,14,15,17-20"
样例3
输入:
plates = [1, 2, 7, 8, 9, 10, 11, 19]
n = 8
输出:
"1,2,7-11,19"
算法原理
解题思路
-
遍历盘子序列:
- 遍历
plates数组,识别出连续递增的子序列。
- 遍历
-
判断子序列长度:
- 如果子序列长度大于等于3,则将其按照
start-end的格式存储。 - 如果子序列长度小于3,则逐个列出所有盘子的序号。
- 如果子序列长度大于等于3,则将其按照
-
处理最后一个子序列:
- 遍历完成后,检查最后一个子序列,进行同样的长度判断和格式存储。
-
输出结果:
- 将所有子序列结果用
,拼接,形成最终字符串。
- 将所有子序列结果用
时间复杂度
- 遍历数组的时间复杂度:。
- 处理结果的时间复杂度:。
总时间复杂度:。
空间复杂度
- 存储结果列表的空间复杂度:。
- 其他常数级变量。
总空间复杂度:。
Go 实现
package main
import (
"fmt"
"strconv"
"strings"
)
func solution(plates []int, n int) string {
if n == 0 {
return ""
}
// 初始化结果集和当前区间的起点和终点
var result []string
start := plates[0]
end := plates[0]
for i := 1; i < n; i++ {
if plates[i] == plates[i-1]+1 { // 如果当前盘子与前一个盘子连续
end = plates[i]
} else {
// 处理当前区间
if end-start >= 2 { // 区间长度 >= 3
result = append(result, fmt.Sprintf("%d-%d", start, end))
} else { // 区间长度 < 3,逐个输出
for j := start; j <= end; j++ {
result = append(result, strconv.Itoa(j))
}
}
// 开始新的区间
start = plates[i]
end = plates[i]
}
}
// 处理最后一个区间
if end-start >= 2 { // 区间长度 >= 3
result = append(result, fmt.Sprintf("%d-%d", start, end))
} else { // 区间长度 < 3,逐个输出
for j := start; j <= end; j++ {
result = append(result, strconv.Itoa(j))
}
}
// 合并结果为字符串
return strings.Join(result, ",")
}
func main() {
// 测试用例
fmt.Println(solution([]int{-3, -2, -1, 2, 10, 15, 16, 18, 19, 20}, 10) == "-3--1,2,10,15,16,18-20")
fmt.Println(solution([]int{-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}, 20) == "-6,-3-1,3-5,7-11,14,15,17-20")
fmt.Println(solution([]int{1, 2, 7, 8, 9, 10, 11, 19}, 8) == "1,2,7-11,19")
}
Python 实现
def solution(plates, n):
if n == 0:
return ""
result = [] # 存储最终结果
start = plates[0] # 当前区间的起点
end = plates[0] # 当前区间的终点
for i in range(1, n):
if plates[i] == plates[i - 1] + 1: # 如果连续
end = plates[i]
else:
# 处理当前区间
if end - start >= 2: # 如果区间长度 >= 3
result.append(f"{start}-{end}")
else: # 否则逐个输出
result.extend(map(str, range(start, end + 1)))
# 开始新的区间
start = plates[i]
end = plates[i]
# 处理最后一个区间
if end - start >= 2: # 如果区间长度 >= 3
result.append(f"{start}-{end}")
else: # 否则逐个输出
result.extend(map(str, range(start, end + 1)))
# 返回结果字符串
return ",".join(result)
if __name__ == "__main__":
# 测试用例
print(solution([-3, -2, -1, 2, 10, 15, 16, 18, 19, 20], 10) == "-3--1,2,10,15,16,18-20")
print(solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20], 20) == "-6,-3-1,3-5,7-11,14,15,17-20")
print(solution([1, 2, 7, 8, 9, 10, 11, 19], 8) == "1,2,7-11,19")
strings.Join
在 Go 中,strings.Join 是一个非常常用的函数,用来将字符串切片中的元素连接成一个单一的字符串,并且可以指定连接时使用的分隔符。
函数签名
func Join(elems []string, sep string) string
-
参数:
elems []string:字符串切片,表示要连接的字符串数组。sep string:分隔符,指定在连接时用来分隔字符串的内容。
-
返回值:
- 返回一个字符串,包含
elems中的所有元素,并用sep分隔。
- 返回一个字符串,包含
示例代码
示例 1:简单连接字符串
package main
import (
"fmt"
"strings"
)
func main() {
// 定义一个字符串切片
words := []string{"Go", "is", "awesome"}
// 使用 strings.Join
result := strings.Join(words, " ")
fmt.Println(result)
}
输出:
Go is awesome
说明:
words是一个字符串切片,包含"Go","is","awesome"。- 使用
" "作为分隔符,最终得到"Go is awesome"。
示例 2:用逗号分隔
package main
import (
"fmt"
"strings"
)
func main() {
// 定义一个字符串切片
words := []string{"apple", "banana", "cherry"}
// 使用 strings.Join
result := strings.Join(words, ", ")
fmt.Println(result)
}
输出:
apple, banana, cherry
示例 3:没有分隔符
package main
import (
"fmt"
"strings"
)
func main() {
// 定义一个字符串切片
words := []string{"123", "456", "789"}
// 使用 strings.Join,无分隔符
result := strings.Join(words, "")
fmt.Println(result)
}
输出:
123456789
示例 4:空切片处理
如果传入的是空切片,strings.Join 返回空字符串。
package main
import (
"fmt"
"strings"
)
func main() {
// 定义一个空切片
var words []string
// 使用 strings.Join
result := strings.Join(words, ", ")
fmt.Println(result) // 输出为空字符串
}
输出:
<空白>
注意事项
-
性能:
strings.Join在底层会一次性计算出最终字符串的长度,然后创建最终字符串。这比手动拼接字符串效率更高。
-
参数类型:
-
elems必须是[]string类型。如果是其他类型的切片(如[]int),需要先转换成[]string,比如:package main import ( "fmt" "strconv" "strings" ) func main() { // 定义一个整数切片 nums := []int{1, 2, 3, 4, 5} // 将整数切片转换为字符串切片 strNums := make([]string, len(nums)) for i, num := range nums { strNums[i] = strconv.Itoa(num) } // 使用 strings.Join result := strings.Join(strNums, ", ") fmt.Println(result) }输出:
1, 2, 3, 4, 5
-
-
空分隔符:
- 如果
sep为空字符串,结果是直接拼接elems中的所有元素,没有任何分隔符。
- 如果