给你两个字符串 a 和 b ,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefix 和 bsuffix ,满足 b = bprefix + bsuffix 。请你判断 aprefix + bsuffix 或者 bprefix + asuffix 能否构成回文串。
当你将一个字符串 s 分割成 sprefix 和 ssuffix 时, ssuffix 或者 sprefix 可以为空。比方说, s = “abc” 那么 “” + “abc” , “a” + “bc” , “ab” + “c” 和 “abc” + “” 都是合法分割。
如果 能构成回文字符串 ,那么请返回 true,否则返回 false 。
注意, x + y 表示连接字符串 x 和 y 。
示例 1:
输入:a = “x”, b = “y”
输出:true
解释:如果 a 或者 b 是回文串,那么答案一定为 true ,因为你可以如下分割:
aprefix = “”, asuffix = “x”
bprefix = “”, bsuffix = “y”
那么 aprefix + bsuffix = “” + “y” = “y” 是回文串。
class Solution {
public boolean checkPalindromeFormation(String a, String b) {
return check(a, b) || check(b, a);
}
// 判断四种情况:a, b, ap+bs, bp+as
private boolean check(String a, String b) {
int i = 0, j = a.length() - 1;
while (i < j && a.charAt(i) == b.charAt(j)) { // 前后缀尽可能匹配
i++;
j--;
}
if (i >= j) { // 判断 a, b 回文 无需分割
return true;
}
return isPalindrome(a, i, j) || isPalindrome(b, i, j); // 判断 aP+bS, bP+aS
}
// ap+bs-> (a 前缀 + 判断中间的串是否回文 + b 后缀)
// 判断剩下的a[idx:len-idx] 或 b[idx:len-idx], 如果是回文串加上对应的aP和bS则可得到完整结果
private boolean isPalindrome(String s, int i, int j) {
while (i < j && s.charAt(i) == s.charAt(j)) {
i++;
j--;
}
return i >= j;
}
}
给你一个长度为 n 的整数数组 nums ,和一个长度为 m 的整数数组 queries 。
返回一个长度为 m 的数组 answer ,其中 answer[i] 是 nums 中 元素之和小于等于 queries[i] 的 子序列 的 最大 长度 。
子序列 是由一个数组删除某些元素(也可以不删除)但不改变剩余元素顺序得到的一个数组。
示例 1:
输入:nums = [4,5,2,1], queries = [3,10,21]
输出:[2,3,4]
解释:queries 对应的 answer 如下:
class Solution {
// 2、排序 前缀和 二分查找
public int[] answerQueries(int[] nums, int[] queries) {
Arrays.sort(nums);
for (int i = 1; i < nums.length; i++) { // nums 原地求前缀和
nums[i] += nums[i - 1];
}
int[] answer = new int[queries.length];
for (int i = 0; i < queries.length; i++) { // queries 遍历二分查找小于等于位置
answer[i] = binarySearch(nums, queries[i]);
}
return answer;
}
public static int binarySearch(int[] nums, int n) {
int l = 0, r = nums.length;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] <= n) {
l = mid + 1; // 下标从 0 开始,大于queries[i]的自序列个数
} else {
r = mid;
}
}
return l;
}
// 1、暴力查找
public int[] answerQueries1(int[] nums, int[] queries) {
Arrays.sort(nums);
int[] answer = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int sum = 0;
for (int j = 0; j < nums.length; j++) {
sum += nums[j];
if (sum <= queries[i]) {
answer[i]++;
}
}
}
return answer;
}
}
一个字符串如果没有 三个连续 相同字符,那么它就是一个 好字符串 。
给你一个字符串 s ,请你从 s 删除 最少 的字符,使它变成一个 好字符串 。
请你返回删除后的字符串。题目数据保证答案总是 唯一的 。
示例 1:
输入:s = “leeetcode”
输出:“leetcode”
解释:
从第一组 ‘e’ 里面删除一个 ‘e’ ,得到 “leetcode” 。
没有连续三个相同字符,所以返回 “leetcode” 。
class Solution {
public String makeFancyString(String s) {
StringBuilder stringBuilder = new StringBuilder();
for (char c : s.toCharArray()) {
// stringBuilder 大于2个开始比较
int len = stringBuilder.length();
if (len >= 2 && stringBuilder.charAt(len - 1) == c && stringBuilder.charAt(len - 2) == c) { // 当前字符与前两个字符相同
continue;
}
stringBuilder.append(c);
}
return stringBuilder.toString();
}
}
你正在参加一场比赛,给你两个 正 整数 initialEnergy 和 initialExperience 分别表示你的初始精力和初始经验。
另给你两个下标从 0 开始的整数数组 energy 和 experience,长度均为 n 。
你将会 依次 对上 n 个对手。第 i 个对手的精力和经验分别用 energy[i] 和 experience[i] 表示。当你对上对手时,需要在经验和精力上都 严格 超过对手才能击败他们,然后在可能的情况下继续对上下一个对手。
击败第 i 个对手会使你的经验 增加 experience[i],但会将你的精力 减少 energy[i] 。
在开始比赛前,你可以训练几个小时。每训练一个小时,你可以选择将增加经验增加 1 或者 将精力增加 1 。
返回击败全部 n 个对手需要训练的 最少 小时数目。
示例 1:
输入:initialEnergy = 5, initialExperience = 3, energy = [1,4,3,2], experience = [2,6,3,1]
输出:8
解释:在 6 小时训练后,你可以将精力提高到 11 ,并且再训练 2 个小时将经验提高到 5 。
按以下顺序与对手比赛:
class Solution {
public int minNumberOfHours(int initialEnergy, int initialExperience, int[] energy, int[] experience) {
int res = 0;
for (int i = 0; i < energy.length; i++) {
if (initialEnergy <= energy[i]) {
res += energy[i] - initialEnergy + 1; // 训练至比对手多 1
initialEnergy = energy[i] + 1;
}
if (initialExperience <= experience[i]) {
res += experience[i] - initialExperience + 1; //
initialExperience = experience[i] + 1;
}
initialEnergy -= energy[i];
initialExperience += experience[i];
}
return res;
}
}
给你一个下标从 0 开始的整数数组 nums 以及一个目标元素 target 。
目标下标 是一个满足 nums[i] == target 的下标 i 。
将 nums 按 非递减 顺序排序后,返回由 nums 中目标下标组成的列表。如果不存在目标下标,返回一个 空 列表。返回的列表必须按 递增 顺序排列。
示例 1:
输入:nums = [1,2,5,2,3], target = 2
输出:[1,2]
解释:排序后,nums 变为 [1,2,2,3,5] 。
满足 nums[i] == 2 的下标是 1 和 2 。
class Solution {
// 排序 遍历 数值等于 target 的元素的下标
public List<Integer> targetIndices1(int[] nums, int target) {
Arrays.sort(nums);
List<Integer> list = new ArrayList();
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target) {
list.add(i);
}
}
return list;
}
// 二分查找 等于 target的下标
// 在排序后数组中,这些数值等于 target 的元素的下标(如果存在)一定是连续的。寻找目标下标的左边界和目标下标的数量来构造目标下标数组
// 目标下标即为的 [cnt1, cnt1 + cnt2) 左闭右开区间内的所有整数
public List<Integer> targetIndices(int[] nums, int target) {
int cnt1 = 0; // 小于 target 的数量
int cnt2 = 0; // 等于 target 的数量
for (int n : nums) {
if (n < target) {
cnt1++;
} else if (n == target) {
cnt2++;
}
}
List<Integer> list = new ArrayList<>();
for (int i = cnt1; i < cnt1 + cnt2; i++) {
list.add(i); // 加入区间的整数
}
return list;
}
}
给你字符串 key 和 message ,分别表示一个加密密钥和一段加密消息。解密 message 的步骤如下:
使用 key 中 26 个英文小写字母第一次出现的顺序作为替换表中的字母 顺序 。
将替换表与普通英文字母表对齐,形成对照表。
按照对照表 替换 message 中的每个字母。
空格 ’ ’ 保持不变。
例如,key = “happy boy”(实际的加密密钥会包含字母表中每个字母 至少一次),据此,可以得到部分对照表(‘h’ -> ‘a’、‘a’ -> ‘b’、‘p’ -> ‘c’、‘y’ -> ‘d’、‘b’ -> ‘e’、‘o’ -> ‘f’)。
返回解密后的消息。
示例 1:
输入:key = “the quick brown fox jumps over the lazy dog”, message = “vkbs bs t suepuv”
输出:“this is a secret”
解释:对照表如上图所示。
提取 “the quick brown fox jumps over the lazy dog” 中每个字母的首次出现可以得到替换表。
输入:key = “eljuxhpwnyrdgtqkviszcfmabo”, message = “zwx hnfx lqantp mnoeius ycgk vcnjrdb”
输出:“the five boxing wizards jump quickly”
解释:对照表如上图所示。
提取 “eljuxhpwnyrdgtqkviszcfmabo” 中每个字母的首次出现可以得到替换表。
提示:
26 <= key.length <= 2000
key 由小写英文字母及 ’ ’ 组成
key 包含英文字母表中每个字符(‘a’ 到 ‘z’)至少一次
1 <= message.length <= 2000
message 由小写英文字母和 ’ ’ 组成
class Solution {
public static String decodeMessage(String key, String message) {
char cur = 'a';
HashMap<Character, Character> map = new HashMap<>(); // 26 英文字母与 key 的对照
for (int i = 0; i < key.length(); i++) {
char c = key.charAt(i);
if (c != ' ' && !map.containsKey(c)) { // key 中 a-z 可能出现多次,保存第一次出现的位置
map.put(c, cur++);
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < message.length(); i++) {
char c = message.charAt(i);
if (c != ' ') { // 根据 map 替换 message,空格 ' ' 保持不变
c = map.get(c);
}
stringBuilder.append(c);
}
return stringBuilder.toString();
}
}