最少字符串操作次数 | 豆包MarsCode AI刷题

73 阅读3分钟

最少字符串操作次数 | 豆包MarsCode AI刷题

最少字符串操作次数 - MarsCode

简单模拟了一下,并且贪心地选用出现频率最低的字符进行插入操作


摘要

给定一个只包含小写字母的字符串 SS,目标是使字符串中的所有字符都不同。每次操作可以将两个相同的字符删除,并在末尾添加一个任意小写字母。我们需要最少的操作次数。


问题描述

小U得到了一个只包含小写字母的字符串 SS,她可以执行以下操作:

  1. 选择字符串中的两个相同字符并将其删除。
  2. 在字符串末尾添加一个任意的小写字母。

小U希望知道,最少需要多少次操作,才能使字符串中的所有字母都互不相同?


测试样例

示例 1

输入:

S = "abab"

输出:

2

示例 2

输入:

S = "aaaa"

输出:

2

示例 3

输入:

S = "abcabc"

输出:

3

算法原理

核心思路

  1. 统计字符频率

    • 使用一个数组 cnt 统计字符串中每个字符的出现次数。
  2. 重复字符的处理

    • 如果某个字符的频率大于 1,可以通过“删除两个相同字符并添加一个新字符”的方式,逐步减少重复字符的数量。
  3. 最优选择新字符

    • 每次选择操作时,优先选择当前计数最少的字符作为新添加的字符,以减少后续重复字符的数量。
  4. 模拟整个过程

    • 模拟整个字符删除和添加过程,统计最少操作次数。

时间复杂度

  1. 统计字符频率O(n)O(n),其中 nn 是字符串长度。
  2. 模拟操作:在最坏情况下,需要遍历整个字符频率数组 2626 次,因此复杂度为 O(26n)O(26 \cdot n)

总时间复杂度O(n)O(n)2626 是常数)。


空间复杂度

需要一个固定大小的数组存储字符频率。

总空间复杂度O(1)O(1)


Go 实现

package main

import (
	"fmt"
)

func solution(S string) int {
	// 字符频率统计
	cnt := [26]int{}
	for i := 0; i < len(S); i++ {
		cnt[S[i]-'a']++
	}

	operations := 0 // 操作计数
	flag := true    // 标记是否需要继续操作

	// 模拟操作过程
	for flag {
		flag = false
		for i := 0; i < 26; i++ {
			if cnt[i] >= 2 {
				// 如果某个字符频率大于等于2,则需要进行一次操作
				flag = true
				cnt[i] -= 2

				// 找到当前计数最少的字符
				minCnt := len(S) + 1
				ptr := -1
				for j := 0; j < 26; j++ {
					if cnt[j] < minCnt {
						minCnt = cnt[j]
						ptr = j
					}
				}

				// 合并新字符
				cnt[ptr]++
				operations++
			}
		}
	}

	return operations
}

func main() {
	fmt.Println(solution("abab") == 2)  // 应输出 true
	fmt.Println(solution("aaaa") == 2)  // 应输出 true
	fmt.Println(solution("abcabc") == 3) // 应输出 true
}

Python 实现

def solution(S: str) -> int:
    """
    对字符串 S 中的字符进行操作,每次将两个相同字符合并为一个新字符。
    返回完成所有操作所需的总步骤数。
    """
    # 初始化字符计数器
    cnt = [0] * 26
    for char in S:
        cnt[ord(char) - ord('a')] += 1

    operations = 0  # 操作计数

    # 模拟合并操作
    flag = True
    while flag:
        flag = False
        for i in range(26):
            if cnt[i] >= 2:
                flag = True
                cnt[i] -= 2

                # 找到当前计数最少的字符
                min_cnt = len(S) + 1
                ptr = -1
                for j in range(26):
                    if cnt[j] < min_cnt:
                        min_cnt = cnt[j]
                        ptr = j

                # 合并新字符
                cnt[ptr] += 1
                operations += 1

    return operations


if __name__ == "__main__":
    # 测试用例
    print(solution("abab") == 2)  # 应输出 True
    print(solution("aaaa") == 2)  # 应输出 True
    print(solution("abcabc") == 3)  # 应输出 True

输出解释

示例 1:

输入:

S = "abab"
  • 操作 1:删除两个 a,添加一个新字符 c
  • 操作 2:删除两个 b,添加一个新字符 d。 结果:最少操作次数为 2

示例 2:

输入:

S = "aaaa"
  • 操作 1:删除两个 a,添加一个新字符 b
  • 操作 2:删除两个 a,添加一个新字符 c。 结果:最少操作次数为 2

示例 3:

输入:

S = "abcabc"
  • 操作 1:删除两个 a,添加一个新字符 d
  • 操作 2:删除两个 b,添加一个新字符 e
  • 操作 3:删除两个 c,添加一个新字符 f。 结果:最少操作次数为 3