力扣链接:3138. 同位字符串连接的最小长度
力扣难度
中等算法评级: 5 熟练掌握常用数据结构和算法,初步了解高级数据结构 难度分 1979
题目: 给你一个字符串 s ,它由某个字符串 t 和若干 t 的 同位字符串 连接而成。
请你返回字符串 t 的 最小 可能长度。
同位字符串 指的是重新排列一个单词得到的另外一个字符串,原来字符串中的每个字符在新字符串中都恰好只使用一次。
示例 1:
输入:s = “abba”
输出:2
解释:
一个可能的字符串 t 为 “ba” 。
示例 2:
输入:s = “cdef”
输出:4
解释:
一个可能的字符串 t 为 “cdef” ,注意 t 可能等于 s 。
提示:
- 1 <= s.length <= 105
- s 只包含小写英文字母。
func minAnagramLength(s string) int {
}
枚举
设 s字符串的长度为n,阅读题目可得提供的s一定是由 字符串 t构成的。(有确定的结)
因此我们输出的结果可能是 n ~ 1,中的其中一个
假设字符串的t的长度为k,k的长度为 1,2,3,4,5,n/2,n
因此我们只要枚举字符串的t的长度为k,然后判断是否符合条件。
题目要求请你返回字符串 t 的 最小 可能长度。因此从小到大遍历,符合条件就退出
func minAnagramLength(s string) int {
n := len(s)
k := 1
record := make(map[byte]int)
for ; k <= n/2; k++ {
record[s[k-1]]++
//
// 到这里就要检测剩下的字符串 是否都是按照 长度 k 来划分了
// K = 1 时 剩下的字符串 为 n - 1 从下标k出发
{ // 不能整除 一点机会都没有
if n%k != 0 {
continue
}
}
sig := 1
for i := k; i < n; i += k {
// 这里面就是按照k去划分
back := copymap(record)
// i 为k下标 加一
// 按照长度为k去划分
for j := 0; j < k; j++ {
back[s[i+j]]--
}
if checkmap(back) { // 存在不符合的
sig++
}
}
if k*sig == n {
return k
}
}
if k > n/2 {
return n
}
return k
}
func copymap(in map[byte]int) map[byte]int {
out := make(map[byte]int)
for k, v := range in {
out[k] = v
}
return out
}
func checkmap(in map[byte]int) bool {
ans := true
for _, v := range in {
if v != 0 {
return false
}
}
return ans
}
优化
都是小写字母储存 因此不用map 直接用长度为26的字母去存储
func minAnagramLength(s string) int {
n := len(s)
record := [26]int{}
for k := 1; k <= n/2; k++ {
record[s[k-1]-'a']++
// 到这里就要检测剩下的字符串 是否都是按照 长度 k 来划分了
// K = 1 时 剩下的字符串 为 n - 1 从下标k出发
{ // 不能整除 一点机会都没有
if n%k != 0 {
continue
}
}
sig := 1
for i := k; i < n; i += k {
// 这里面就是按照k去划分
back := record
// i 为k下标 加一
// 按照长度为k去划分
for j := 0; j < k; j++ {
back[s[i+j]-'a']--
}
if check(back) { // 存在不符合的
sig++
}
}
if k*sig == n {
return k
}
}
return n
}
func check(in [26]int) bool {
ans := true
for _, v := range in {
if v != 0 {
return false
}
}
return ans
}