modify code

master
algorithmzuo 2 years ago
parent b975d71de0
commit d774ec7d9e

@ -0,0 +1,73 @@
package class_2023_04_2_week;
import java.util.PriorityQueue;
// 来自学员问题,来自真实笔试
// 景区里有m个项目也就是项目数组为int[][] game这是一个m*2的二维数组
// 景区的第i个项目有如下两个参数
// game[i] = { Ki, Bi }
// Ki一定是负数Bi一定是正数
// 举个例子 :
// Ki = -2, Bi = 10
// 如果只有1个人买票单张门票的价格为 : Ki * 1 + Bi = 8
// 所以这1个人游玩该项目要花8元
// 如果有2个人买票单张门票的价格为 : Ki * 2 + Bi = 6
// 所以这2个人游玩该项目要花6 * 2 = 12元
// 如果有5个人买票单张门票的价格为 : Ki * 2 + Bi = 0
// 所以这5个人游玩该项目要花0 * 5 = 0元
// 如果有更多人买票都认为花0元(因为你让项目倒贴钱实在是太操蛋了)
// 于是可以认为如果有x个人买票单张门票的价格为 : Ki * x + Bi
// x个人游玩这个项目的总花费是 : max { (Ki * x + Bi) * x , 0 }
// 你作为领导单位一共有n个人每个人最多可以选1个项目来游玩也可以不选任何项目
// 所有员工将在明晚提交选择,然后由你去按照上面的规则,统一花钱,统一购票
// 但是现在,你想知道自己需要准备多少钱,就可以应付可能的各种情况,
// 支持各种可能下的开销,返回这个最保险的钱数
// 数据量描述 :
// 1 <= N、M、Bi <= 10^5
// -(10^5) <= Ki < 0
public class Code01_GroupBuyTickets {
// n个人
//
public static int enoughMoney(int n, int[][] games) {
PriorityQueue<Game> heap = new PriorityQueue<>((a, b) -> b.earn() - a.earn());
// m * log m
for (int[] g : games) {
heap.add(new Game(g[0], g[1]));
}
int ans = 0;
// n * log m
for (int i = 0; i < n; i++) {
if (heap.peek().earn() <= 0) {
break;
}
Game cur = heap.poll();
ans += cur.earn();
cur.people++;
heap.add(cur);
}
return ans;
}
public static class Game {
public int Ki;
public int Bi;
// 已经来了多少人
// 每来一个人,票价,减少 | K |
public int people;
public Game(int k, int b) {
Ki = k;
Bi = b;
people = 0;
}
// 如果再来一个人,景区还能收获多少钱 ?
public int earn() {
// return (Ki * (people + 1) + Bi) + Ki * people;
return (2 * people + 1) * Ki + Bi;
}
}
}

@ -0,0 +1,75 @@
package class_2023_04_2_week;
import java.util.Arrays;
// 来自小红书
// 实验室需要配制一种溶液现在研究员面前有n种该物质的溶液
// 每一种有无限多瓶第i种的溶液体积为v[i]里面含有w[i]单位的该物质
// 研究员每次可以选择一瓶溶液,
// 将其倒入另外一瓶(假设瓶子的容量无限),即可以看作将两个瓶子内的溶液合并
// 此时合并的溶液体积和物质含量都等于之前两个瓶子内的之和。
// 特别地如果瓶子A与B的溶液体积相同那么A与B合并之后
// 该物质的含量会产生化学反应使得该物质含量增加x单位
// 研究员的任务是配制溶液体积恰好等于c的且尽量浓的溶液(即物质含量尽量多)
// 研究员想要知道物质含量最多是多少
// 对于所有数据1 <= n, v[i], w[i], x, c <= 1000
public class Code02_ChemicalProblem {
public static int maxValue(int[] v, int[] w, int x, int c) {
int n = v.length;
// dp[0] ? dp[1] ? dp[2] ? dp[c] ?
int[] dp = new int[c + 1];
// dp[i] = -1, 得到i体积目前为止无方案
Arrays.fill(dp, -1);
// 天然有的规格,先填一下
for (int i = 0; i < n; i++) {
// 3 10 dp[3] = 10
// 5 13 dp[5] = 13
// 3 20 dp[3] = 20
if (v[i] <= c) {
dp[v[i]] = Math.max(dp[v[i]], w[i]);
}
}
// 1 ? 2 ? 3 ? c ? dp[1....c]
for (int i = 1; i <= c; i++) {
// i = 10体积
// 1 + 9
// 2 + 8
// 3 + 7
// 4 + 6
// 5 + 5 + x
for (int j = 1; j <= i / 2; j++) {
// dp[10] = dp[1] + dp[9]
// 能得到 能得到
if (dp[j] != -1 && dp[i - j] != -1) {
dp[i] = Math.max(dp[i],
dp[j] + dp[i - j] + (j == i - j ? x : 0));
}
}
}
return dp[c];
}
public static void main(String[] args) {
// 调配溶液
// 规格0 (体积5含量2)
// 规格1 (体积3含量4)
// 规格2 (体积4含量1)
// 合并双方体积不等的情况下 :
// (体积5含量2) + (体积4含量1) = (体积9含量3)
// 合并双方体积相等的情况下 :
// (体积5含量5) + (体积5含量2) = (体积10含量5 + 2 + x)
// x额外增加固定int类参数x= 10
// c一定要得到c体积的溶液含量最大能是多少 ?
int[] v = { 5, 3, 4 };
int[] w = { 2, 4, 1 };
int x = 4;
int c = 16;
// (体积3含量4) + (体积3含量4) = (体积6含量12)
// (体积3含量4) + (体积3含量4) = (体积6含量12)
// (体积6含量12) + (体积6含量12) = (体积12含量28)
// (体积12含量28) + (体积4含量1) = (体积16含量29)
System.out.println(maxValue(v, w, x, c));
}
}

@ -0,0 +1,38 @@
package class_2023_04_2_week;
import java.util.Arrays;
// 来自谷歌、亚马逊、微软、蔚来、腾讯、字节跳动、Uber
// 给出两个长度相同的字符串 str1 和 str2
// 请你帮忙判断字符串 str1 能不能在 零次 或 多次 转化 后变成字符串 str2
// 每一次转化时,你可以将 str1 中出现的 所有 相同字母变成其他 任何 小写英文字母
// 只有在字符串 str1 能够通过上述方式顺利转化为字符串 str2 时才能返回 true 。​​
// 测试链接 : https://leetcode.cn/problems/string-transforms-into-another-string/
public class Code03_StringTransformsIntoAnotherString {
public static boolean canConvert(String str1, String str2) {
if (str1.equals(str2)) {
return true;
}
int[] map = new int[26];
int kinds = 0;
for (int i = 0; i < str2.length(); i++) {
if (map[str2.charAt(i) - 'a']++ == 0) {
kinds++;
}
}
if (kinds == 26) {
return false;
}
Arrays.fill(map, -1);
for (int i = 0; i < str1.length(); i++) {
int cur = str1.charAt(i) - 'a';
if (map[cur] != -1 && str2.charAt(map[cur]) != str2.charAt(i)) {
return false;
}
map[cur] = i;
}
return true;
}
}

@ -0,0 +1,92 @@
package class_2023_04_2_week;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
// 来自Indeed、谷歌、亚马逊、领英、英伟达
// 一个坐标可以从 -infinity 延伸到 +infinity 的 无限大的 棋盘上
// 你的 骑士 驻扎在坐标为 [0, 0] 的方格里。
// 骑士的走法和中国象棋中的马相似,走 “日” 字:
// 即先向左(或右)走 1 格,再向上(或下)走 2 格
// 或先向左(或右)走 2 格,再向上(或下)走 1 格
// 每次移动,他都可以像中国象棋中的马一样,选八个方向中的一个前进
// 返回 骑士前去征服坐标为 [x, y] 的部落所需的最小移动次数
// 本题确保答案是一定存在的。
// 测试链接 : https://leetcode.cn/problems/minimum-knight-moves/
public class Code04_MinimumKnightMoves {
// A*算法的实现
public static int minKnightMoves(int x, int y) {
// int[] cur = {
// 0 : 出发点到当前位置跳了几次
// 1 : 当前位置跳到目标位置,估计还要跳几次
// 2 : 当前位置的行
// 3 : 当前位置的列
// f() : 出发点到当前位置跳了几次,谁次数少,谁先弹出
// f() + g() :
PriorityQueue<int[]> heap = new PriorityQueue<>(
(a, b) -> (a[0] + a[1]) - (b[0] + b[1]));
// 从堆里弹出了什么位置,不要重复再考虑了
HashMap<Integer, HashSet<Integer>> closed = new HashMap<>();
heap.add(new int[] { 0, distance(0, 0, x, y), 0, 0 });
int ans = Integer.MAX_VALUE;
while (!heap.isEmpty()) {
int[] cur = heap.poll();
int cost = cur[0];
int row = cur[2];
int col = cur[3];
if (isPoped(closed, row, col)) {
continue;
}
if (row == x && col == y) {
ans = cost;
break;
}
close(closed, row, col);
add(cost + 1, row + 2, col + 1, x, y, closed, heap);
add(cost + 1, row + 1, col + 2, x, y, closed, heap);
add(cost + 1, row - 1, col + 2, x, y, closed, heap);
add(cost + 1, row - 2, col + 1, x, y, closed, heap);
add(cost + 1, row - 2, col - 1, x, y, closed, heap);
add(cost + 1, row - 1, col - 2, x, y, closed, heap);
add(cost + 1, row + 1, col - 2, x, y, closed, heap);
add(cost + 1, row + 2, col - 1, x, y, closed, heap);
}
return ans;
}
// 如果之间弹出过(r,c)点返回true
// 如果之间没弹出过(r,c)点返回false
public static boolean isPoped(HashMap<Integer, HashSet<Integer>> closed, int r, int c) {
return closed.containsKey(r) && closed.get(r).contains(c);
}
// 把(r,c)点加入closed表
public static void close(HashMap<Integer, HashSet<Integer>> closed, int r, int c) {
if (!closed.containsKey(r)) {
closed.put(r, new HashSet<>());
}
closed.get(r).add(c);
}
public static void add(int cost, int r, int c, int x, int y, HashMap<Integer, HashSet<Integer>> closed,
PriorityQueue<int[]> heap) {
if (!isPoped(closed, r, c)) {
heap.add(new int[] { cost, distance(r, c, x, y), r, c });
}
}
// 曼哈顿距离 / 3
// 为什么要定成这个
// 因为估计函数的估计代价 要小于等于 真实代价
// 我们知道,走"日"字是一次蹦3个曼哈顿距离
// 如果A点到B点的曼哈顿距离是3不是任意的A和B都能通过走"日"的方式,一步达到的
// 所以真实代价 >= 曼哈顿距离 / 3
// 那就把 曼哈顿距离 / 3定成估计函数
public static int distance(int r, int c, int x, int y) {
return (Math.abs(x - r) + Math.abs(y - c)) / 3;
}
}

@ -0,0 +1,356 @@
package class_2023_04_2_week;
// 来自小红书、谷歌、Bloomberg、微软、亚马逊、字节跳动、摩根大通、Uber
// 你会得到一个字符串 text
// 你应该把它分成 k 个子字符串 (subtext1, subtext2 subtextk)
// 要求满足:
// subtexti 是 非空 字符串
// 所有子字符串的连接等于 text
// ( 即subtext1 + subtext2 + ... + subtextk == text )
// subtexti == subtextk - i + 1 表示所有 i 的有效值( 即 1 <= i <= k )
// 返回k可能最大值。
// 测试链接 : https://leetcode.cn/problems/longest-chunked-palindrome-decomposition/
public class Code05_LongestChunkedPalindromeDecomposition {
// 时间复杂度O(N^2)
// 题解上的做法
// 但这不是最优解
// 而且没有帖子写出最优解
public static int longestDecomposition1(String str) {
if (str.length() == 1) {
return 1;
}
char[] s = str.toCharArray();
int n = s.length;
int l = 0;
int r = n - 1;
int ans = 0;
while (l <= r) {
int size = 1;
for (; 2 * size <= r - l + 1; size++) {
if (same1(s, l, r, size)) {
break;
}
}
if (2 * size <= r - l + 1) {
ans += 2;
}
l += size;
r -= size;
}
return r == l - 1 ? ans : (ans + 1);
}
public static boolean same1(char[] s, int l, int r, int size) {
for (int i = l, j = r - size + 1; j <= r; i++, j++) {
if (s[i] != s[j]) {
return false;
}
}
return true;
}
// 时间复杂度O(N * logN)
// 最优解
// 利用DC3算法生成后缀数组、进而生成高度数组来做的
// 需要体系学习班DC3生成后缀数组详解
// 不过Leetcode的数据量太小根本显不出最优解的优异
// 所以我自己写了测试来展示
public static int longestDecomposition2(String str) {
if (str.length() == 1) {
return 1;
}
char[] s = str.toCharArray();
int n = s.length;
DC3 dc3 = generateDC3(s, n);
int[] rank = dc3.rank;
RMQ rmq = new RMQ(dc3.height);
int l = 0;
int r = n - 1;
int ans = 0;
while (l <= r) {
int size = 1;
for (; 2 * size <= r - l + 1; size++) {
if (same2(rank, rmq, l, r, size)) {
break;
}
}
if (2 * size <= r - l + 1) {
ans += 2;
}
l += size;
r -= size;
}
return r == l - 1 ? ans : (ans + 1);
}
public static boolean same2(int[] rank, RMQ rmq, int l, int r, int size) {
int start1 = l;
int start2 = r - size + 1;
int minStart = Math.min(rank[start1], rank[start2]);
int maxStart = Math.max(rank[start1], rank[start2]);
return rmq.min(minStart + 1, maxStart) >= size;
}
public static DC3 generateDC3(char[] s, int n) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (char cha : s) {
min = Math.min(min, cha);
max = Math.max(max, cha);
}
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = s[i] - min + 1;
}
return new DC3(arr, max - min + 1);
}
public static class DC3 {
public int[] sa;
public int[] rank;
public int[] height;
public DC3(int[] nums, int max) {
sa = sa(nums, max);
rank = rank();
height = height(nums);
}
private int[] sa(int[] nums, int max) {
int n = nums.length;
int[] arr = new int[n + 3];
for (int i = 0; i < n; i++) {
arr[i] = nums[i];
}
return skew(arr, n, max);
}
private int[] skew(int[] nums, int n, int K) {
int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2;
int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3];
for (int i = 0, j = 0; i < n + (n0 - n1); ++i) {
if (0 != i % 3) {
s12[j++] = i;
}
}
radixPass(nums, s12, sa12, 2, n02, K);
radixPass(nums, sa12, s12, 1, n02, K);
radixPass(nums, s12, sa12, 0, n02, K);
int name = 0, c0 = -1, c1 = -1, c2 = -1;
for (int i = 0; i < n02; ++i) {
if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) {
name++;
c0 = nums[sa12[i]];
c1 = nums[sa12[i] + 1];
c2 = nums[sa12[i] + 2];
}
if (1 == sa12[i] % 3) {
s12[sa12[i] / 3] = name;
} else {
s12[sa12[i] / 3 + n0] = name;
}
}
if (name < n02) {
sa12 = skew(s12, n02, name);
for (int i = 0; i < n02; i++) {
s12[sa12[i]] = i + 1;
}
} else {
for (int i = 0; i < n02; i++) {
sa12[s12[i] - 1] = i;
}
}
int[] s0 = new int[n0], sa0 = new int[n0];
for (int i = 0, j = 0; i < n02; i++) {
if (sa12[i] < n0) {
s0[j++] = 3 * sa12[i];
}
}
radixPass(nums, s0, sa0, 0, n0, K);
int[] sa = new int[n];
for (int p = 0, t = n0 - n1, k = 0; k < n; k++) {
int i = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2;
int j = sa0[p];
if (sa12[t] < n0 ? leq(nums[i], s12[sa12[t] + n0], nums[j], s12[j / 3])
: leq(nums[i], nums[i + 1], s12[sa12[t] - n0 + 1], nums[j], nums[j + 1], s12[j / 3 + n0])) {
sa[k] = i;
t++;
if (t == n02) {
for (k++; p < n0; p++, k++) {
sa[k] = sa0[p];
}
}
} else {
sa[k] = j;
p++;
if (p == n0) {
for (k++; t < n02; t++, k++) {
sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2;
}
}
}
}
return sa;
}
private void radixPass(int[] nums, int[] input, int[] output, int offset, int n, int k) {
int[] cnt = new int[k + 1];
for (int i = 0; i < n; ++i) {
cnt[nums[input[i] + offset]]++;
}
for (int i = 0, sum = 0; i < cnt.length; ++i) {
int t = cnt[i];
cnt[i] = sum;
sum += t;
}
for (int i = 0; i < n; ++i) {
output[cnt[nums[input[i] + offset]]++] = input[i];
}
}
private boolean leq(int a1, int a2, int b1, int b2) {
return a1 < b1 || (a1 == b1 && a2 <= b2);
}
private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) {
return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3));
}
private int[] rank() {
int n = sa.length;
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
ans[sa[i]] = i;
}
return ans;
}
private int[] height(int[] s) {
int n = s.length;
int[] ans = new int[n];
for (int i = 0, k = 0; i < n; ++i) {
if (rank[i] != 0) {
if (k > 0) {
--k;
}
int j = sa[rank[i] - 1];
while (i + k < n && j + k < n && s[i + k] == s[j + k]) {
++k;
}
ans[rank[i]] = k;
}
}
return ans;
}
}
public static class RMQ {
public int[][] min;
public RMQ(int[] arr) {
int n = arr.length;
int k = power2(n);
min = new int[n + 1][k + 1];
for (int i = 1; i <= n; i++) {
min[i][0] = arr[i - 1];
}
for (int j = 1; (1 << j) <= n; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
min[i][j] = Math.min(min[i][j - 1], min[i + (1 << (j - 1))][j - 1]);
}
}
}
public int min(int l, int r) {
l++;
r++;
int k = power2(r - l + 1);
return Math.min(min[l][k], min[r - (1 << k) + 1][k]);
}
private int power2(int m) {
int ans = 0;
while ((1 << ans) <= (m >> 1)) {
ans++;
}
return ans;
}
}
// 为了测试
public static String generateS(int a, int b) {
char[] ans = new char[a + b];
for (int i = 0; i < a; i++) {
ans[i] = 'a';
}
for (int i = a, j = 0; j < b; i++, j++) {
ans[i] = 'b';
}
return String.valueOf(ans);
}
// 为了测试
public static String generateT(String part, int n) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < n; i++) {
builder.append(part);
}
return builder.toString();
}
// 为了测试
public static void main(String[] args) {
System.out.println("先展示一下DC3的用法");
String test = "aaabaaa";
DC3 dc3 = generateDC3(test.toCharArray(), test.length());
System.out.println("sa[i]表示字典序排名第i的是什么位置开头的后缀串");
int[] sa = dc3.sa;
for (int i = 0; i < test.length(); i++) {
System.out.println(i + " : " + sa[i]);
}
System.out.println("rank[i]表示i位置开头的后缀串的字典序排多少名");
int[] rank = dc3.rank;
for (int i = 0; i < test.length(); i++) {
System.out.println(i + " : " + rank[i]);
}
System.out.println("height[i]表示字典序排名i的后缀串和前一个排名的后缀串最长公共前缀是多长");
int[] height = dc3.height;
for (int i = 0; i < test.length(); i++) {
System.out.println(i + " : " + height[i]);
}
System.out.println("性能测试开始");
long start, end;
// 构造一个字符串s
// s = a....一共30万个a....ab
String s = generateS(300000, 1);
// 构造总的字符串t
// t = s + s
// t的总长度是60万长度 -> 6 * 10^5
String t = generateT(s, 2);
// longestDecomposition1跑完是很慢的
// 耐心等吧运行时间在15秒左右
start = System.currentTimeMillis();
System.out.println("方法1的结果 : " + longestDecomposition1(t));
end = System.currentTimeMillis();
System.out.println("方法1的运行时间 : " + (end - start) + " 毫秒");
// longestDecomposition2跑完是很快的
// 而且你构造不出让longestDecomposition2方法慢的例子
// 字符串长度在10^6以内可以随意构造字符串
// longestDecomposition2方法都会很快
start = System.currentTimeMillis();
System.out.println("方法2的结果 : " + longestDecomposition2(t));
end = System.currentTimeMillis();
System.out.println("方法2的运行时间 : " + (end - start) + " 毫秒");
System.out.println("性能测试结束");
}
}

@ -3371,6 +3371,79 @@ projects[i] = {a, b}
第065节 2023年4月第2周流行算法题目解析
来自学员问题,来自真实笔试
景区里有m个项目也就是项目数组为int[][] game这是一个m*2的二维数组
景区的第i个项目有如下两个参数
game[i] = { Ki, Bi } Ki一定是负数Bi一定是正数
举个例子 :
Ki = -2, Bi = 10
如果只有1个人买票单张门票的价格为 : Ki * 1 + Bi = 8
所以这1个人游玩该项目要花8元
如果有2个人买票单张门票的价格为 : Ki * 2 + Bi = 6
所以这2个人游玩该项目要花6 * 2 = 12元
如果有5个人买票单张门票的价格为 : Ki * 2 + Bi = 0
所以这5个人游玩该项目要花0 * 5 = 0元
如果有更多人买票都认为花0元(因为你让项目倒贴钱实在是太操蛋了)
于是可以认为如果有x个人买票单张门票的价格为 : Ki * x + Bi
x个人游玩这个项目的总花费是 : max { (Ki * x + Bi) * x , 0 }
你作为领导单位一共有n个人每个人最多可以选1个项目来游玩也可以不选任何项目
所有员工将在明晚提交选择,然后由你去按照上面的规则,统一花钱,统一购票
但是现在,你想知道自己需要准备多少钱,就可以应付可能的各种情况,
支持各种可能下的开销,返回这个最保险的钱数
数据量描述 :
1 <= N、M、Bi <= 10^5
-(10^5) <= Ki < 0
来自小红书
实验室需要配制一种溶液现在研究员面前有n种该物质的溶液
每一种有无限多瓶第i种的溶液体积为v[i]里面含有w[i]单位的该物质
研究员每次可以选择一瓶溶液,
将其倒入另外一瓶(假设瓶子的容量无限),即可以看作将两个瓶子内的溶液合并
此时合并的溶液体积和物质含量都等于之前两个瓶子内的之和。
特别地如果瓶子A与B的溶液体积相同那么A与B合并之后
该物质的含量会产生化学反应使得该物质含量增加x单位
研究员的任务是配制溶液体积恰好等于c的且尽量浓的溶液(即物质含量尽量多)
研究员想要知道物质含量最多是多少
对于所有数据1 <= n, v[i], w[i], x, c <= 1000
来自谷歌、亚马逊、微软、蔚来、腾讯、字节跳动、Uber
给出两个长度相同的字符串 str1 和 str2
请你帮忙判断字符串 str1 能不能在 零次 或 多次 转化 后变成字符串 str2
每一次转化时,你可以将 str1 中出现的 所有 相同字母变成其他 任何 小写英文字母
只有在字符串 str1 能够通过上述方式顺利转化为字符串 str2 时才能返回 true 。​​
测试链接 : https://leetcode.cn/problems/string-transforms-into-another-string/
来自Indeed、谷歌、亚马逊、领英、英伟达
一个坐标可以从 -infinity 延伸到 +infinity 的 无限大的 棋盘上
你的 骑士 驻扎在坐标为 [0, 0] 的方格里。
骑士的走法和中国象棋中的马相似,走 “日” 字:
即先向左(或右)走 1 格,再向上(或下)走 2 格
或先向左(或右)走 2 格,再向上(或下)走 1 格
每次移动,他都可以像中国象棋中的马一样,选八个方向中的一个前进
返回 骑士前去征服坐标为 [x, y] 的部落所需的最小移动次数
本题确保答案是一定存在的。
测试链接 : https://leetcode.cn/problems/minimum-knight-moves/
来自小红书、谷歌、Bloomberg、微软、亚马逊、字节跳动、摩根大通、Uber
你会得到一个字符串 text
你应该把它分成 k 个子字符串 (subtext1, subtext2 subtextk)
要求满足:
subtexti 是 非空 字符串
所有子字符串的连接等于 text
( 即subtext1 + subtext2 + ... + subtextk == text )
subtexti == subtextk - i + 1 表示所有 i 的有效值( 即 1 <= i <= k )
返回k可能最大值。
测试链接 : https://leetcode.cn/problems/longest-chunked-palindrome-decomposition/

Loading…
Cancel
Save