算法 - 贪心算法 - 周赛 - 100242. 满足距离约束且字典序最小的字符串

本文讲述了如何使用贪心策略解决LeetCode问题,通过限定操作次数,找到字典序最小的字符串,同时满足字符间距离不超过给定值k。
摘要由CSDN通过智能技术生成

100242. 满足距离约束且字典序最小的字符串

说明

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

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

字符 '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" 。
 

提示:

1 <= s.length <= 100
0 <= k <= 2000
s 只包含小写英文字母。

题解思路

贪心

  • 根据题意简单理解下
    1. 有k个可以操作的点数
    2. 需要找字典序最小的(字典序最小也就是——越前面的越靠近a最优先)
  • 即得到一个贪心策略
    • 遍历字符串的每个字符
    • 如果当前字符与a的距离小于k,则说明当前的字符可以等于’a’,字典序最小,应当判断下一位
    • 如果当前字符与a的距离大于k,则说明当前字符不能等于’a’,则当前字符减去k,操作点数用完,直接
  • 优化一下就是,如果当前字符与a的距离大于k,操作点数用完,直接返回;否则将此位置为’a’,k减去当前距离
  • 关于dis的取法:
    • 一开始按题意写的,方法有保留
    • 后来优化了一下,取该字符和’a’与’z’+1 (a的两种表示)之间更小的那个就可以了

Code

贪心

class Solution {
    public String getSmallestString(String s, int k) {
        char[] cs = s.toCharArray();
        for(int i = 0; i < cs.length; i++){
            // int dis = dis(cs[i], 'a');
            int dis = Math.min(cs[i] - 'a', 'z' - cs[i] + 1);
            if (dis > k){
                cs[i] -= k;
                return new String(cs);
            }
            cs[i] = 'a';
            k -= dis;
        }
        return new String(cs);
    }
    
    private int dis(char c1, char c2){
        int i1 = (c1 > c2 ? c1 : c2) - 'a';
        int i2 = (c1 > c2 ? c2 : c1) - 'a';
        int d = Math.abs(i1 - i2);
        if(d > 12){
            d = Math.abs(i2 + 26 - i1);
        }
        return d;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值