力扣刷题之3106.满足距离约束且字典序最小的字符串

题干描述

给你一个字符串 s 和一个整数 k

定义函数 distance(s1, s2) ,用于衡量两个长度为 n 的字符串 s1s2 之间的距离,即:

  • 字符 'a''z'循环 顺序排列,对于区间 [0, n - 1] 中的 i ,计算所有「 s1[i]s2[i] 之间最小距离 」的

例如,distance("ab", "cd") == 4 ,且 distance("a", "z") == 1

你可以对字符串 s 执行任意次 操作。在每次操作中,可以将 s 中的一个字母 改变任意其他小写英文字母。

返回一个字符串,表示在执行一些操作后你可以得到的 字典序最小 的字符串 t ,且满足 distance(s, t) <= k

示例 1:

复制代码
输入:s = "zbbz", k = 3
输出:"aaaz"
解释:在这个例子中,可以执行以下操作:
将 s[0] 改为 'a' ,s 变为 "abbz" 。
将 s[1] 改为 'a' ,s 变为 "aabz" 。
将 s[2] 改为 'a' ,s 变为 "aaaz" 。
"zbbz" 和 "aaaz" 之间的距离等于 k = 3 。
可以证明 "aaaz" 是在任意次操作后能够得到的字典序最小的字符串。
因此,答案是 "aaaz" 。

示例 2:

复制代码
输入:s = "xaxcd", k = 4
输出:"aawcd"
解释:在这个例子中,可以执行以下操作:
将 s[0] 改为 'a' ,s 变为 "aaxcd" 。
将 s[2] 改为 'w' ,s 变为 "aawcd" 。
"xaxcd" 和 "aawcd" 之间的距离等于 k = 4 。
可以证明 "aawcd" 是在任意次操作后能够得到的字典序最小的字符串。
因此,答案是 "aawcd" 。

示例 3:

复制代码
输入:s = "lol", k = 0
输出:"lol"
解释:在这个例子中,k = 0,更改任何字符都会使得距离大于 0 。
因此,答案是 "lol" 。

题干解析

首先我们需要先了解题干中的距离是指什么?事实上这个距离是一个在字符串操作中的概念,可以理解为一种特殊的字符变换距离。具体来说,它衡量的是两个字符串在最小变换次数从一个字符串变换为另一个字符串的难度。在这道题目中定义了一种字符的循环排列(即'a' 到'z',然后在回到'a'),并规定了这种循环排列中的字符变换距离。

距离定义

我们来详细解释一下这种距离:

1.字符距离:两个字符之间的距离是他们在循环排列中的最小变换次数,例如
  • 字符'a'到'b'之间的距离是1,因为它们相邻。
  • 字符'a'到'z'的距离也是1,因为在循环排列中。从'a'到'z'只需要一次变换。
2.字符串距离:两个字符串之间的距离也是1,因为在循环排列中,从'a'到'z'只需要一次变换。

对于字符串"ab"和"cd":

  • 'a'到'c'的距离是2(a->b->c) 。
  • 'b'到'd'的距离是2(b->c->d)。

因此distance("ab", "cd") = 2 + 2 = 4

字典序

字典序是指在字符串在字典中的排列顺序。例如,按照字典序排列时,apple排在banana之前。为了得到字典序最小的字符串,我们应该尽可能将字符改为字母表中最小的字母a。

题目分析

这道题目要求我们通过人一次操作将给定的字符串s转换成一个新的字符串t,使得两个字符串s和t之间的距离不超过k,并且要使得到的字符串t在字典序上尽可能小。

1.字符循环排列:
  • 题目定义了字符a到z按循环顺序排列。两个字符之间的距离是它们在这个循环中的最小距离。例如,字符a和z之间的距离是1,因为它们在循环中的最小距离是1。
2.字符串距离:
  • 两个字符串之间的距离是所有对应位置字符之间的距离之和。例如,distance("ab", "cd")等于4,因为a到c的距离是2,b到d的距离也是2。
3.操作:
  • 每次操作可以将字符串中的一个字母变成任何其他小写字母。

解题步骤

1.计算字符串距离
  • 我们需要计算字符串s和t之间的距离。字符a到z按循环顺序排列,所以字符之间的距离是它们在循环中的最小距离。
2.贪心策略
  • 为了使字符串的字典序最小,我们应该尽可能多地将字符改为a,因为a在字典序中最小。
3.逐字符处理:

从字符串的左边开始,逐字符处理:

  • 计算将当前字符变成a所需的最小距离。
  • 如果距离小于等于k,则将当前字符变成a,并更新剩余的k。
  • 如果距离大于k,则根据剩余的k调整当前字符,确保不超过k的限制,然后结束。
cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <math.h>

char* getSmallestString(char* s, int k) {
	int len = strlen(s);
	for (int i = 0; i < len; ++i)
	{
		//计算将当前字符变成'a'所需的最小距离
		int dis = fmin(s[i] - 'a', 'z' - s[i] + 1);
		if (dis <= k)
		{
			//距离小于等于k则将字母变成a
			s[i] = 'a';
			k -= dis;
		}
		else {
			//否则,将字符减去k,但需要考虑字符循环的情况
			int newChar = s[i] - k;
			if (newChar < 'a')
			{
				newChar += 26;//循环处理,回到z之后
			}
			s[i] = (char)newChar;
			break;
		}
	}
	return s;
}
int main() {
	char s1[] = "zbbz";
	int k1 = 3;
	printf("Result: %s\n", getSmallestString(s1, k1)); // 输出应为 "aaaz"

	char s2[] = "xaxcd";
	int k2 = 4;
	printf("Result: %s\n", getSmallestString(s2, k2)); // 输出应为 "aawcd"

	char s3[] = "lol";
	int k3 = 0;
	printf("Result: %s\n", getSmallestString(s3, k3)); // 输出应为 "lol"

	return 0;
}
相关推荐
柠檬少少开发9 分钟前
图像拼接算法及实现(一)
人工智能·算法·计算机视觉
jnrjian19 分钟前
USE_CONCAT in list OR 以及 filter Nest LOOP
数据结构·list
阿华的代码王国26 分钟前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
weixin_486681141 小时前
C++系列-STL容器中统计算法count, count_if
开发语言·c++·算法
一道秘制的小菜1 小时前
C++第七节课 运算符重载
服务器·开发语言·c++·学习·算法
标标大人2 小时前
c语言中的局部跳转以及全局跳转
android·c语言·开发语言
代码小狗Codog2 小时前
C++独立开发开源大数计算库 CBigNum
数据结构·c++
咕噜咕嘟嘟嘟2 小时前
343. 整数拆分
数据结构·算法
WenGyyyL3 小时前
力扣最热一百题——二叉树的直径
java·c++·算法·二叉树·深度优先
sdlkjaljafdg3 小时前
vector<bool>性能测试
开发语言·c++·算法