具有给定数值的最小字符串
题目描述
小写字符 的 数值 是它在字母表中的位置(从 1 开始),因此 a 的数值为 1 ,b 的数值为 2 ,c 的数值为 3 ,以此类推。
字符串由若干小写字符组成,字符串的数值 为各字符的数值之和。例如,字符串 “abe” 的数值等于 1 + 2 + 5 = 8 。
给你两个整数 n 和 k 。返回 长度 等于 n 且 数值 等于 k 的 字典序最小 的字符串。
注意,如果字符串 x 在字典排序中位于 y 之前,就认为 x 字典序比 y 小,有以下两种情况:
- x 是 y 的一个前缀;
- 如果 i 是 x[i] != y[i] 的第一个位置,且 x[i] 在字母表中的位置比 y[i] 靠前。
样例
样例输入
n = 3, k = 27
n = 5, k = 73
样例输出
“aay” 字符串的数值为 1 + 1 + 25 = 27,它是数值满足要求且长度等于 3 字典序最小的字符串。
“aaszz”
提示
- 1<=n<=1051 <= n <= 10^51<=n<=105
- n<=k<=26∗nn <= k <= 26 * nn<=k<=26∗n
思路
贪心思想,要使得z越多,在字典序中就会越小,答案格式是开头0...n0...n0...n个a
与结尾0...n0...n0...n个z
组成, 中间存在或不存在一个不等于a
或不得与z
的小写字母。
代码实现
class Solution {public String getSmallestString(int n, int k) {char[] s = new char[n];Arrays.fill(s, 'a');int m = (k - n) % 25;int z = (k - n) / 25;if(m != 0) s[n - z - 1] = (char)('a' + m);for(int i = n - z; i < n; i++){s[i] = 'z';} return String.valueOf(s);}
}
命运石之门的选择
题目描述
在某一条不知名世界线的冈伦今天突然接到了一条dmail,上面说世界线将会发生巨大变动,未来的他无论如何都无法扭转这种变动回到原来的世界线。而世界线变动的原因是现在的他不久后错过了与助手的约会。他约好要和助手去约会,但是在去约会之前,由于一直拖欠房租,房东大叔要求他帮忙完成一幅画的上色,然而他没有以最快的速度完成这个任务,导致他错过了与助手的约会,从而导致世界线的剧变。现在到了拯救世界的时候,由于冈伦并不擅长画画,于是他找到了同样不擅长画画的你来帮他解决这个问题(这是命运石之门的选择)。不管怎样现在拯救世界的重任交到了你的手上,而你虽然不擅长画画,但是你可以使用编程来帮助你解决这个问题。
这幅画十分抽象:它由N个宽度为1高度为Hi的矩形组成,矩形并排排列,相邻的矩形间没有空隙,初始情况下每个矩形都是没有颜色的。你有一个宽度为1的刷子,你可以竖直或水平的刷,每次使用刷子,你的刷子都必须保证一直全部处于矩形中,即不能刷到矩形以外的地方去,当然你每次刷的时候也不能拐弯。你每刷一次,要花费1的时间,这和刷的长度无关,比如你可以从最左边刷到最右边(当然是不经过矩形以外的部分),这也只花费1的时间。你的目的是将全部的矩形都涂满颜色。请输出这个最短的时间,以便冈伦决定是自己来完成这个任务还是让你来做苦力。
输入格式
第1行:一个正整数N,表示矩形的个数。
接下来N个正整数Hi,表示第i个矩形的高度。
输出格式
一个整数,表示最少花费的时间。
样例 #1
样例输入 #1
5
2 2 1 2 1
样例输出 #1
3
提示
【数据规模】
3030% N<=20, Hi<=10030
6060% N<=100, Hi<=100060
100100% N<=5,000, Hi<=10^9100
思路
分治思想,每次以区间的最低点为分割点,分别开始递归计算。
代码实现
import java.util.*;public class Main{static int[] arr; public static void main(String[] args){Scanner sc = new Scanner(System.in);int len = sc.nextInt();arr = new int[len+1];for(int i = 1; i <= len; i++) arr[i] = sc.nextInt();System.out.println(divide(1, len, 0));sc.close();}private static int divide(int l, int r, int depth){if(l > r) return 0;if(l == r) return 1;int cnt = 0, min = 1000000001;for(int i = l; i <= r; i++) min = Math.min(min, arr[i]);int left = l;for(int i = l; i <= r; i++){if(arr[i] - min == 0){cnt += divide(left, i - 1, min);left = i + 1;}}cnt += divide(left, r, min);return Math.min(r - l + 1, cnt + (min - depth));}
}