具有给定数值的最小字符串【LC1663】
The numeric value of a lowercase character is defined as its position
(1-indexed)
in the alphabet, so the numeric value ofa
is1
, the numeric value ofb
is2
, the numeric value ofc
is3
, 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 to1 + 2 + 5 = 8
.You are given two integers
n
andk
. Return the lexicographically smallest string with length equal ton
and numeric value equal tok
.Note that a string
x
is lexicographically smaller than stringy
ifx
comes beforey
in dictionary order, that is, eitherx
is a prefix ofy
, or ifi
is the first position such thatx[i] != y[i]
, thenx[i]
comes beforey[i]
in alphabetic order.
-
思路:贪心
局部最优:在保证字符串长度一定,优先在字符串尾部插入数值最大的字符,即使首部字符串尽可能为a、尾部字符串尽可能为z
全局最优:字符串的字典顺序最小
-
实现【总体超时】
从尾部开始插入字符,当n和k一定时,前 n − 1 n-1 n−1个字符需要的分数最少为 n − 1 n-1 n−1,那么可供第 n n n个字符使用的分数为 k − ( n − 1 ) k-(n-1) k−(n−1),因此第 n n n个字符一定
- 如果
k
−
(
n
−
1
)
>
=
26
k-(n-1)>=26
k−(n−1)>=26,那么尾部可以插入的最小字符为
z='a'+25
,贡献的分数为 26 26 26 - 如果
k
−
(
n
−
1
)
<
26
k-(n-1)<26
k−(n−1)<26,那么尾部可以插入的最小字符为
'a' + k-n
,贡献的分数为 k − n + 1 k-n+1 k−n+1
class Solution { public String getSmallestString(int n, int k) { StringBuilder sb = new StringBuilder(); while (n > 0){ if (k - n + 1 >= 26){ sb.insert(0, (char)('a' + 25)); k -= 26; }else{ sb.insert(0, (char)('a' + k - n)); k -= k - n + 1; } n--; } return sb.toString(); } }
- 复杂度
- 时间复杂度: O ( n 2 ) O(n^2) O(n2),每构造一位字符需要将字符串后移一位,需要的时间复杂度为 O ( n ) O(n) O(n),因此总时间复杂度为 O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( 1 ) O(1) O(1)
- 如果
k
−
(
n
−
1
)
>
=
26
k-(n-1)>=26
k−(n−1)>=26,那么尾部可以插入的最小字符为
-
实现
从头部开始插入字符,当 n n n和 k k k一定时,使前面的字符尽可能为a,后面的字符尽可能为z。当构造第 i i i个字符时,后 n − i n-i n−i个字符全为z需要的分数为 ( n − i ) ∗ 26 (n-i)*26 (n−i)∗26,那么第 i i i个字符需要贡献的分数为 m a x ( 1 , k − ( n − i ) ∗ 26 ) max(1,k-(n-i)*26) max(1,k−(n−i)∗26)
- 如果
k
−
(
n
−
i
)
∗
26
>
1
k-(n-i)*26>1
k−(n−i)∗26>1,那么表示尾部全部插入z,仍有分数剩余,那么第
i
i
i个字符应插入
'a'+k-(n-i)*26-1
,贡献的分数为 k − ( n − i ) ∗ 26 k-(n-i)*26 k−(n−i)∗26 - 如果
k
−
(
n
−
i
)
∗
26
<
=
1
k-(n-i)*26<=1
k−(n−i)∗26<=1,那么表示尾部全部插入z,没有分数剩余甚至还有同于,那么第
i
i
i个字符可以插入的最小字符
'a'
,贡献的分数为 1 1 1
class Solution { public String getSmallestString(int n, int k) { StringBuilder sb = new StringBuilder(); while (n > 0){ int lower = Math.max(1, k - (n - 1) * 26); sb.append((char)('a'+ lower - 1)); k -= lower; n--; } return sb.toString(); } }
- 复杂度
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
- 如果
k
−
(
n
−
i
)
∗
26
>
1
k-(n-i)*26>1
k−(n−i)∗26>1,那么表示尾部全部插入z,仍有分数剩余,那么第
i
i
i个字符应插入