1663. Smallest String With A Given Numeric Value

题目:

The numeric value of a lowercase character is defined as its position (1-indexed) in the alphabet, so the numeric value of a is 1, the numeric value of b is 2, the numeric value of c is 3, and so on.

The numeric value of a string consisting of lowercase characters is defined as the sum of its characters' numeric values. For example, the numeric value of the string "abe" is equal to 1 + 2 + 5 = 8.

You are given two integers n and k. Return the lexicographically smallest string with length equal to n and numeric value equal to k.

Note that a string x is lexicographically smaller than string y if x comes before y in dictionary order, that is, either x is a prefix of y, or if i is the first position such that x[i] != y[i], then x[i] comes before y[i] in alphabetic order.

 

Example 1:

Input: n = 3, k = 27
Output: "aay"
Explanation: The numeric value of the string is 1 + 1 + 25 = 27, and it is the smallest string with such a value and length equal to 3.

Example 2:

Input: n = 5, k = 73
Output: "aaszz"

 

Constraints:

  • 1 <= n <= 10^5
  • n <= k <= 26 * n

 

思路1:

题意大概是给出n和k两个整数,n表示字符串长度,k表示字母总和,返回字典序列最小的符合n和k的字符串。k的总和是通过字符串中的字符计算的,'a'=1,'b'=2,依此类推'z'=26。很明显字典序列最小那开头肯定尽量是字母’a‘了,所以我们应该从最后一位开始考虑。我的方法是从26,即'z'开始,如果分出i个z,剩下的全是a,这种情况的总和等于k,则我们找到了解;如果大于k,说明位数n给的太小,字母‘z’太大了,但是n是定值,只能'z'退一位变成'y',然后再重新计算,这里每次更换字符,i的大小要变成原本给定的n,并且要从大到小递减,否则可能会超时;如果小于k,说明当前的方案是可以的,但是剩下的位数不能全是'a',比如k=30和n=3,减了个26还剩4,但是不可以剩下2位都是‘a',这样的话k就是26+1+1=28不符合30了,这种情况下我们把能分配的'z'先分配了,分配出去i个,然后'z'退格,然后更新i的大小,以及n和k,更新i的大小和上面一种情况一样。这种方法比较繁琐,但是能够通过,大概是80ms。

 

代码1:

class Solution {
public:
    string getSmallestString(int n, int k) {
        string ans = "";
        int c = 26;
        int num = n;
        for (int i = n; i >=1; i--)
        {
            if (c * i + n - i > k)
            {
                if (i == 1)
                {
                    c--;
                    i = num;
                }
            }
            else if (c * i + n - i < k)
            {
                k -= i*c;
                n-=i;
                char temp = c + 'a'-1;
                string s(i, temp);
                ans = s + ans;
                i = num;
                c--;
            }
            else
            {
                n-=i;
                char temp = c + 'a' - 1;
                string s(i, temp);
                ans = s + ans;
                break;
            }
        }
        string add(n, 'a');
        ans = add + ans;
        return ans;
    }
};

 

思路2:

看了大神的O(n)做法,大概是60ms即可通过。首先是分配一个长为n,每一位都是'a’的string,然后从最后一位,假设为i,开始更新,只要k大于0,那么这一轮在i位要加上的就是min(k, 25),这里25是因为本来就是'a',只要加25即可变成’z‘。这样无论是不是剩下的k是不是超出了26,只要一轮一轮比较,都可以按照比较得到的值去分配,不用像思路1中考虑三种情况了。

 

代码2:

class Solution {
public:
    string getSmallestString(int n, int k) {
        string ans(n,'a');
        k-=n;
        int i=n-1;
        while(k>0)
        {
            int add = min(k, 25);
            ans[i]+=add;
            k-=add;
            i--;
        }
        return ans;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值