前言
最近,字节跳动的青训营再次扬帆起航,作为第二次参与其中的小北,深感荣幸能借此机会为那些尚未了解青训营的友友们带来一些详细介绍。青训营不仅是一个技术学习与成长的摇篮,更是一个连接未来与梦想的桥梁~
1、报名方式
2、考核内容
在指定的题库中自主选择不少于 15 道算法题并完成解题,其中题目难度分配如下:
- 简单题不少于 10 道
- 中等题不少于 4 道
- 困难题不少于 1 道
eg:解答代码(困难2题)
1、二进制之和(困难)
# 问题描述 给定两个二进制字符串,返回他们的和(用十进制字符串表示)。输入为非空字符串且只包含数字 1 和 0 ,请考虑大数问题。时间复杂度不要超过 O(n^2),其中 n 是二进制的最大长度。 ## 输入格式 每个样例只有一行,两个二进制字符串以英文逗号“,”分割 ## 输出格式 输出十进制格式的两个二进制的和 **输入样例**: 101,110 **输出样例**: 11 **数据范围**: 每个二进制不超过 100 个字符,JavaScript 语言下请考虑大数的情况。
问题分析:
- 函数签名:string addBinary(const string &a, const string &b):这个函数接收两个二进制字符串,并返回它们的十进制和作为字符串。
- 变量初始化:string result;:用于存储二进制加法的中间和最终结果(在反转之前)。int carry = 0;:初始化进位为0。int i = a.size() - 1; 和 int j = b.size() - 1;:分别初始化两个字符串的索引,从末尾开始遍历。
- 循环逻辑:while (i >= 0 || j >= 0 || carry):当任一字符串还有未处理的位或存在进位时,继续循环。在循环内部,首先处理进位,然后根据索引 i 和 j 的有效性,将对应位置的字符转换为数字并加到 sum 上。更新进位 carry 和结果字符串 result。
- 结果处理:reverse(result.begin(), result.end());:由于是从字符串末尾开始构建结果,因此最后需要反转字符串。long long decimalSum = stoll(result, 0, 2);:将二进制字符串转换为十进制长整数。这一步实际上是多余的,因为题目要求返回的是十进制字符串,而不是长整数。return to_string(decimalSum);:将十进制长整数转换回字符串并返回。由于前面的 stoll 转换是多余的,这一步也可以优化为直接返回 result 字符串(在反转之后)。
初始代码:
def solution(expression): # Please write your code here return -2 if __name__ == "__main__": # You can add more test cases here print(solution("1+1") == 2) print(solution("3+4*5/(3+2)") == 7) print(solution("4+2*5-2/1") == 12) print(solution("(1+(4+5+2)-3)+(6+8)") == 23)
手搓代码:
import java.util.Stack; public class Main { public static int solution(String expression) { Stack<Integer> numStack = new Stack<>(); Stack<Character> opStack = new Stack<>(); // 遍历表达式 for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); // 如果是数字,将其转换为整数并压入数字栈 if (Character.isDigit(c)) { int num = 0; while (i < expression.length() && Character.isDigit(expression.charAt(i))) { num = num * 10 + (expression.charAt(i) - '0'); i++; } i--; numStack.push(num); } // 如果是左括号,直接压入运算符栈 else if (c == '(') { opStack.push(c); } // 如果是右括号,进行计算直到遇到左括号 else if (c == ')') { while (opStack.peek() != '(') { char op = opStack.pop(); int num2 = numStack.pop(); int num1 = numStack.pop(); if (op == '+') { numStack.push(num1 + num2); } else if (op == '-') { numStack.push(num1 - num2); } else if (op == '*') { numStack.push(num1 * num2); } else if (op == '/') { numStack.push(num1 / num2); } } opStack.pop(); } // 如果是运算符,根据优先级进行处理 else if (isOperator(c)) { while (!opStack.isEmpty() && precedence(c) <= precedence(opStack.peek())) { char op = opStack.pop(); int num2 = numStack.pop(); int num1 = numStack.pop(); if (op == '+') { numStack.push(num1 + num2); } else if (op == '-') { numStack.push(num1 - num2); } else if (op == '*') { numStack.push(num1 * num2); } else if (op == '/') { numStack.push(num1 / num2); } } opStack.push(c); } } // 处理剩余的运算符 while (!opStack.isEmpty()) { char op = opStack.pop(); int num2 = numStack.pop(); int num1 = numStack.pop(); if (op == '+') { numStack.push(num1 + num2); } else if (op == '-') { numStack.push(num1 - num2); } else if (op == '*') { numStack.push(num1 * num2); } else if (op == '/') { numStack.push(num1 / num2); } } // 返回数字栈的栈顶元素即为结果 return numStack.pop(); } // 判断是否为运算符 public static boolean isOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/'; } // 定义运算符的优先级 public static int precedence(char op) { if (op == '+' || op == '-') { return 1; } else if (op == '*' || op == '/') { return 2; } return -1; } public static void main(String[] args) { // You can add more test cases here System.out.println(solution("1+1") == 2); System.out.println(solution("3+4*5/(3+2)") == 7); System.out.println(solution("4+2*5-2/1") == 12); System.out.println(solution("(1+(4+5+2)-3)+(6+8)") == 23); } }
AI调试:
def solution(binary1, binary2): # 使用int函数将二进制字符串转换为整数 num1 = int(binary1, 2) num2 = int(binary2, 2) sum_result = num1 + num2 # 计算和 return str(sum_result) # 将结果转换为字符串并返回 # 测试用例 print(solution("101", "110") == "11") print(solution("111111", "10100") == "83") print(solution("111010101001001011", "100010101001") == "242420") print(solution("111010101001011", "10010101001") == "31220")
运行结果:
2、查找热点数据(困难)
# 问题描述
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。
- 1 <= nums.length <= 10^5
- k 的取值范围是 [1, 数组中不相同的元素的个数]
- 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
你所设计算法的时间复杂度必须优于 O(n log n) ,其中 n 是数组大小。
**示例 1**
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
**示例 2**
输入: nums = [1], k = 1
输出: [1]
问题分析:
1、参数:
- vector<int>& nums: 输入的整数数组。
- int k: 需要返回的前k个高频元素的数量。
2、局部变量:
- unordered_map<int, int> freqMap: 用于存储每个数字的频率。
- vector<pair<int,int>> result: 存储哈希表中的键值对(数字及其频率)。
- stringstream ss: 用于构建最终返回的字符串。
3、逻辑流程:
- 构建频率映射: 遍历输入数组 nums,使用 unordered_map 记录每个数字的频率。
- 存储映射到结果向量: 将 freqMap 中的每个键值对(数字及其频率)添加到 result 向量中。
- 排序: 使用 sort 函数对 result 向量进行排序,排序依据是元素的频率(降序)。
- 构建返回字符串: 遍历排序后的 result 向量的前 k 个元素,将它们转换为字符串并使用逗号分隔,存储在 stringstream 中。
- 返回结果: 将 stringstream 中的内容转换为字符串并返回。
最终代码:
import java.util.*;
public class Main {
public static String solution(int[] nums, int k) {
// 使用哈希表记录每个元素的频率
Map<Integer, Integer> freqMap = new HashMap<>();
for (int num : nums) {
freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);
}
// 将频率存储到列表中并按频率排序
List<Map.Entry<Integer, Integer>> resultList = new ArrayList<>(freqMap.entrySet());
resultList.sort((a, b) -> b.getValue().compareTo(a.getValue())); // 按频率降序排序
// 创建结果字符串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++) {
sb.append(resultList.get(i).getKey());
if (i < k - 1) {
sb.append(","); // 添加逗号分隔
}
}
return sb.toString(); // 返回结果字符串
}
public static void main(String[] args) {
// 测试用例
int[] nums1 = {1, 1, 1, 2, 2, 3};
int[] nums2 = {1};
// 输出结果是否与预期相符
System.out.println(solution(nums1, 2).equals("1,2")); // true
System.out.println(solution(nums2, 1).equals("1")); // true
}
}
eg:解答代码(中等4题)
1、简单四则运算解析器 (中等)
初始代码:
def solution(binary1, binary2):
# Please write your code here
return ""
if __name__ == "__main__":
# You can add more test cases here
print(solution("101", "110") == "11")
print(solution("111111", "10100") == "83")
print(solution("111010101001001011", "100010101001") == "242420")
print(solution("111010101001011", "10010101001") == "31220")
手搓代码:
import java.util.Stack;
public class Main {
public static int solution(String expression) {
Stack<Integer> numStack = new Stack<>();
Stack<Character> opStack = new Stack<>();
// 遍历表达式
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
// 如果是数字,将其转换为整数并压入数字栈
if (Character.isDigit(c)) {
int num = 0;
while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
num = num * 10 + (expression.charAt(i) - '0');
i++;
}
i--;
numStack.push(num);
}
// 如果是左括号,直接压入运算符栈
else if (c == '(') {
opStack.push(c);
}
// 如果是右括号,进行计算直到遇到左括号
else if (c == ')') {
while (opStack.peek() != '(') {
char op = opStack.pop();
int num2 = numStack.pop();
int num1 = numStack.pop();
if (op == '+') {
numStack.push(num1 + num2);
} else if (op == '-') {
numStack.push(num1 - num2);
} else if (op == '*') {
numStack.push(num1 * num2);
} else if (op == '/') {
numStack.push(num1 / num2);
}
}
opStack.pop();
}
// 如果是运算符,根据优先级进行处理
else if (isOperator(c)) {
while (!opStack.isEmpty() && precedence(c) <= precedence(opStack.peek())) {
char op = opStack.pop();
int num2 = numStack.pop();
int num1 = numStack.pop();
if (op == '+') {
numStack.push(num1 + num2);
} else if (op == '-') {
numStack.push(num1 - num2);
} else if (op == '*') {
numStack.push(num1 * num2);
} else if (op == '/') {
numStack.push(num1 / num2);
}
}
opStack.push(c);
}
}
// 处理剩余的运算符
while (!opStack.isEmpty()) {
char op = opStack.pop();
int num2 = numStack.pop();
int num1 = numStack.pop();
if (op == '+') {
numStack.push(num1 + num2);
} else if (op == '-') {
numStack.push(num1 - num2);
} else if (op == '*') {
numStack.push(num1 * num2);
} else if (op == '/') {
numStack.push(num1 / num2);
}
}
// 返回数字栈的栈顶元素即为结果
return numStack.pop();
}
// 判断是否为运算符
public static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/';
}
// 定义运算符的优先级
public static int precedence(char op) {
if (op == '+' || op == '-') {
return 1;
} else if (op == '*' || op == '/') {
return 2;
}
return -1;
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution("1+1") == 2);
System.out.println(solution("3+4*5/(3+2)") == 7);
System.out.println(solution("4+2*5-2/1") == 12);
System.out.println(solution("(1+(4+5+2)-3)+(6+8)") == 23);
}
}
AI调试:
def solution(expression):
num_stack = []
op_stack = []
i = 0
while i < len(expression):
c = expression[i]
if c.isdigit():
num = 0
while i < len(expression) and expression[i].isdigit():
num = num * 10 + int(expression[i])
i += 1
i -= 1
num_stack.append(num)
elif c == '(':
op_stack.append(c)
elif c == ')':
while op_stack[-1] != '(':
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
if op == '+':
num_stack.append(num1 + num2)
elif op == '-':
num_stack.append(num1 - num2)
elif op == '*':
num_stack.append(num1 * num2)
elif op == '/':
num_stack.append(num1 // num2) # 使用整数除法
op_stack.pop()
elif is_operator(c):
while op_stack and precedence(c) <= precedence(op_stack[-1]):
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
if op == '+':
num_stack.append(num1 + num2)
elif op == '-':
num_stack.append(num1 - num2)
elif op == '*':
num_stack.append(num1 * num2)
elif op == '/':
num_stack.append(num1 // num2) # 使用整数除法
op_stack.append(c)
i += 1
while op_stack:
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
if op == '+':
num_stack.append(num1 + num2)
elif op == '-':
num_stack.append(num1 - num2)
elif op == '*':
num_stack.append(num1 * num2)
elif op == '/':
num_stack.append(num1 // num2) # 使用整数除法
return num_stack.pop()
def is_operator(c):
return c in '+-*/'
def precedence(op):
if op in '+-':
return 1
elif op in '*/':
return 2
return -1
# 测试用例
print(solution("1+1") == 2)
print(solution("3+4*5/(3+2)") == 7)
print(solution("4+2*5-2/1") == 12)
print(solution("(1+(4+5+2)-3)+(6+8)") == 23)
运行结果:
2、机器人能量冒险(中等)
初始代码:
public class Main {
public static String solution(int n, int[] array) {
// Edit your code here
return "TRUE";
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(5, new int[]{2, 3, 1, 1, 4}).equals("TRUE"));
System.out.println(solution(5, new int[]{3, 2, 1, 0, 4}).equals("FALSE"));
}
}
手搓代码:
public class Main {
public static String solution(int n, int[] array) {
// 初始化当前位置为 0
int currentPosition = 0;
// 循环直到到达最后一个位置或者无法前进
while (currentPosition < n - 1) {
// 如果当前位置的能量值为 0,直接返回 FALSE
if (array[currentPosition] == 0) {
return "FALSE";
}
// 计算可以前进的最大步数
int maxSteps = array[currentPosition];
// 尝试从当前位置前进
for (int step = 1; step <= maxSteps && currentPosition + step < n; step++) {
// 如果能直接到达最后一个位置,返回 TRUE
if (currentPosition + step == n - 1) {
return "TRUE";
}
}
// 选择能前进最远的步数
int bestStep = 0;
for (int step = 1; step <= maxSteps && currentPosition + step < n; step++) {
if (array[currentPosition + step] > array[currentPosition + bestStep]) {
bestStep = step;
}
}
// 前进所选的步数
currentPosition += bestStep;
}
// 如果循环结束还没到达最后一个位置,返回 FALSE
if (currentPosition == n - 1) {
return "TRUE";
} else {
return "FALSE";
}
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(5, new int[] { 2, 3, 1, 1, 4 }).equals("TRUE"));
System.out.println(solution(5, new int[] { 3, 2, 1, 0, 4 }).equals("FALSE"));
}
}
AI调试:
public class Main {
public static String solution(int n, int[] array) {
// 初始化当前能到达的最远位置
int maxReach = 0;
// 遍历数组
for (int i = 0; i < n; i++) {
// 如果当前位置超过了能到达的最远位置,说明无法继续前进
if (i > maxReach) {
return "FALSE";
}
// 更新能到达的最远位置
maxReach = Math.max(maxReach, i + array[i]);
// 如果最远位置已经超过或等于最后一个位置,直接返回 TRUE
if (maxReach >= n - 1) {
return "TRUE";
}
}
// 如果遍历结束还没到达最后一个位置,返回 FALSE
return "FALSE";
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(5, new int[] { 2, 3, 1, 1, 4 }).equals("TRUE"));
System.out.println(solution(5, new int[] { 3, 2, 1, 0, 4 }).equals("FALSE"));
}
}
运行结果:
3、最大异或和计算(中等)
AI调试代码:
public class Main {
public static int solution(int n, int[] a, int[] b) {
// 计算数组 a 和 b 的总和
int sumA = 0;
int sumB = 0;
for (int num : a) {
sumA += num;
}
for (int num : b) {
sumB += num;
}
int maxXor = 0;
// 尝试删除数组 a 中的每一个元素
for (int i = 0; i < n; i++) {
int newSumA = sumA - a[i];
int newSumB = sumB;
maxXor = Math.max(maxXor, newSumA ^ newSumB);
}
// 尝试删除数组 b 中的每一个元素
for (int i = 0; i < n; i++) {
int newSumA = sumA;
int newSumB = sumB - b[i];
maxXor = Math.max(maxXor, newSumA ^ newSumB);
}
return maxXor;
}
public static void main(String[] args) {
System.out.println(solution(3, new int[]{1, 2, 3}, new int[]{3, 2, 1}) == 5);
System.out.println(solution(4, new int[]{4, 5, 6, 7}, new int[]{7, 8, 9, 10}) == 51);
System.out.println(solution(5, new int[]{10, 20, 30, 40, 50}, new int[]{50, 40, 30, 20, 10}) == 248);
}
}
运行结果:
4、数字翻译成字符串的可能性(中等)
AI调试代码:
public class Main {
public static int solution(int num) {
String str = String.valueOf(num); // 将数字转成字符串
int n = str.length();
if (n == 0) return 0;
if (n == 1) return 1; // 单字符的情况
// 动态规划数组
int[] dp = new int[n + 1];
dp[0] = 1; // 空字符串一种方式
dp[1] = 1; // 一个字符也有一种方式
for (int i = 2; i <= n; i++) {
// 只翻译当前字符
dp[i] = dp[i - 1];
// 结合前一个字符一起翻译
int twoDigit = Integer.parseInt(str.substring(i - 2, i)); // 当前字符及前一个字符形成的数
if (twoDigit >= 10 && twoDigit <= 25) {
dp[i] += dp[i - 2]; // 如果能够组合翻译
}
}
return dp[n]; // 返回总的翻译方式
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution(12258) == 5);
System.out.println(solution(1400112) == 6);
System.out.println(solution(2110101) == 10);
}
}
运行结果:
5、五子棋获胜策略(中等)
# 问题描述
- 假设存在一个五子棋棋盘,大小未知。上面只摆放了一些白色的棋子,现在你的手中还有一个白色棋子,要求找出在棋盘的哪些位置摆放这个棋子,能够使棋盘上出现五颗棋子连成一线。
- 备注:棋盘上当前不存在连成一条线的五个棋子,但至少存在一个点能够凑出五子一线(不限于横、竖、斜线)
## 输入格式
- 第一行输入一个正整数 `n`,表示棋盘的宽度,棋盘总共可以容纳 `n^2` 个棋子。
- 第 2 到 `n+1` 行输入 `n` 个数字。每次输入 `n` 个数,其中 `1` 代表有棋子,`0` 代表没有棋子。
## 输出格式
- 如果有 `n` 个可放置点,输出 `n` 行。
- 每行输出两个数字,以空格分隔,分别代表放置点在棋盘上的行数和列数。
- 输出顺序需要按照行数从小到大、列数从小到大的顺序。
## 输入样例
```
6
0 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 0
```
## 输出样例
1 1
6 6
## 数据范围
- 第一行中,棋盘宽度为 `[1, 10)` 中的整数。
- 第 2 到 `n+1` 行中,只会出现 `0` 或 `1`。
问题分析:
这个题目跟小北之前做过的一个题目很像,那个是动态的,双方互相落子判断谁胜利,这个是给你一个棋局,没有黑白方,判断落子胜利有几种方式,原理就是落子时,判断上下左右左斜右斜,且在规定范围内,是否可以达到五子连珠。
AI调试代码:
import java.util.ArrayList;
import java.util.List;
public class Main {
// 检查某个位置是否可以形成五子连线
public static boolean canFormLine(int x, int y, int[][] board, int n) {
// 定义四个方向:右,下,右下,左下
int[][] directions = {
{1, 0}, {0, 1}, {1, 1}, {1, -1}};
for (int[] dir : directions) {
int count = 1; // 当前位置记为1
int dx = dir[0], dy = dir[1];
// 检查正向
for (int step = 1; step < 5; ++step) {
int nx = x + dx * step;
int ny = y + dy * step;
if (nx >= 0 && nx < n && ny >= 0 && ny < n && board[nx][ny] == 1) {
count++;
} else {
break;
}
}
// 检查反向
for (int step = 1; step < 5; ++step) {
int nx = x - dx * step;
int ny = y - dy * step;
if (nx >= 0 && nx < n && ny >= 0 && ny < n && board[nx][ny] == 1) {
count++;
} else {
break;
}
}
// 如果形成五子连接,则返回 true
if (count >= 5) return true;
}
return false; // 没有符合条件的连线
}
// 主解决方案函数
public static int[][] solution(int n, int[][] board) {
List<int[]> results = new ArrayList<>();
// 检查每个位置是否能放置新棋子形成五子连线
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 0) { // 只检查空位
if (canFormLine(i, j, board, n)) {
results.add(new int[]{i + 1, j + 1}); // 记录行列,+1因要求从1开始
}
}
}
}
// 将结果转换为二维数组
int[][] resultArray = new int[results.size()][2];
for (int i = 0; i < results.size(); i++) {
resultArray[i] = results.get(i);
}
return resultArray.length > 0 ? resultArray : new int[][]{}; // 如果没有结果,返回 {-1, -1}
}
public static void main(String[] args) {
// 测试用例
int[][] array = {
{0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0}
};
int[][] expectedOutput = {
{1, 1}, {6, 6}};
System.out.println(java.util.Arrays.deepEquals(solution(6, array), expectedOutput)); // 验证测试结果
}
}
运行结果:
eg:解答代码(简单10题)
1、线上报警问题分类(简单)
AI调试代码:
import java.util.*;
public class Main {
public static List<Integer> solution(int n, int m, int q, int[][] arrayN, int[][] arrayQ) {
// 首先创建一个布尔类型的二维数组来记录每个用户是否命中每个实验
boolean[][] userHitExperiments = new boolean[n][m];
// 遍历用户命中的实验序列,标记相应的位置为 true
for (int i = 0; i < n; i++) {
for (int j = 1; j <= arrayN[i][0]; j++) {
userHitExperiments[i][arrayN[i][j] - 1] = true;
}
}
// 创建一个列表来存储每次查询的结果
List<Integer> result = new ArrayList<>();
// 遍历每次查询的实验序列
for (int i = 0; i < q; i++) {
int count = 0;
// 对于每个用户,检查是否符合查询条件
for (int j = 0; j < n; j++) {
boolean isMatch = true;
for (int k = 1; k <= arrayQ[i][0]; k++) {
// 根据正负号判断是否命中或未命中实验
if ((arrayQ[i][k] > 0 && !userHitExperiments[j][arrayQ[i][k] - 1]) ||
(arrayQ[i][k] < 0 && userHitExperiments[j][-arrayQ[i][k] - 1])) {
isMatch = false;
break;
}
}
// 如果符合条件,计数器加 1
if (isMatch) {
count++;
}
}
result.add(count);
}
return result;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(3, 3, 3, new int[][] { { 2, 1, 2 }, { 2, 2, 3 }, { 2, 1, 3 } },
new int[][] { { 2, 1, -2 }, { 2, 2, -3 }, { 2, 3, -1 } }).equals(Arrays.asList(1, 1, 1)));
}
}
运行结果:
2、版本号比较(简单)
AI调试代码:
public class Main {
public static void main(String[] args) {
System.out.println(solution("0.1", "1.1") == -1);
System.out.println(solution("1.0.1", "1") == 1);
System.out.println(solution("7.5.2.4", "7.5.3") == -1);
System.out.println(solution("1.0", "1.0.0") == 0);
}
public static int solution(String version1, String version2) {
// 首先将版本号按 '.' 分割成修订号数组
String[] revisions1 = version1.split("\\.");
String[] revisions2 = version2.split("\\.");
// 找出较长的修订号数组长度
int maxLength = Math.max(revisions1.length, revisions2.length);
// 逐个比较修订号
for (int i = 0; i < maxLength; i++) {
// 如果当前下标超出了其中一个版本号的修订号数量,视为 0
int revision1 = i < revisions1.length ? Integer.parseInt(revisions1[i]) : 0;
int revision2 = i < revisions2.length ? Integer.parseInt(revisions2[i]) : 0;
// 比较当前修订号
if (revision1 > revision2) {
return 1;
} else if (revision1 < revision2) {
return -1;
}
}
// 如果所有修订号都相等,返回 0
return 0;
}
}
运行结果:
3、字符串字符类型排序问题(简单)
AI调试代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
public class Main {
public static String solution(String inp) {
// 首先,将输入字符串拆分成字符数组
char[] charArray = inp.toCharArray();
// 分别创建用于存储数字、字母和问号的列表
List<Character> numbers = new ArrayList<>();
List<Character> letters = new ArrayList<>();
List<Integer> questionMarkIndices = new ArrayList<>();
// 遍历字符数组,将数字、字母和问号分别存储到对应的列表中,并记录问号的位置
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (Character.isDigit(c)) {
numbers.add(c);
} else if (Character.isAlphabetic(c)) {
letters.add(c);
} else if (c == '?') {
questionMarkIndices.add(i);
}
}
// 对数字列表进行从大到小排序
numbers.sort((a, b) -> b - a);
// 对字母列表进行字典序排序
letters.sort(Comparator.naturalOrder());
// 重新构建输出字符串
StringBuilder output = new StringBuilder();
int numIndex = 0;
int letterIndex = 0;
for (int i = 0; i < charArray.length; i++) {
if (questionMarkIndices.contains(i)) {
output.append('?');
} else if (Character.isDigit(charArray[i])) {
output.append(numbers.get(numIndex++));
} else if (Character.isAlphabetic(charArray[i])) {
output.append(letters.get(letterIndex++));
}
}
return output.toString();
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution("12A?zc").equals("21A?cz"));
System.out.println(solution("1Ad?z?t24").equals("4Ad?t?z21"));
System.out.println(solution("???123??zxy?").equals("???321??xyz?"));
}
}
运行结果:
4、连续子串和的整除问题(简单)
AI调试代码:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int n, int b, List<Integer> sequence) {
int count = 0; // 用于计数满足条件的连续子串
// 遍历整个序列
for (int i = 0; i < n; i++) {
// 对于每个起始位置 i,计算从 i 开始的连续子串的和
int sum = 0;
for (int j = i; j < n; j++) {
sum += sequence.get(j);
// 判断当前子串的和是否能被 b 整除
if (sum % b == 0) {
// 如果能整除,计数加 1
count++;
}
}
}
// 返回计数结果
return count;
}
public static void main(String[] args) {
// 测试用例
List<Integer> sequence = new ArrayList<>();
sequence.add(1);
sequence.add(2);
sequence.add(3);
// 检查函数返回值是否等于预期值
System.out.println(solution(3, 3, sequence) == 3); // 应该输出 true
}
}
运行结果:
5、完美整数(简单)
AI调试代码:
public class Main {
public static int solution(int x, int y) {
int count = 0; // 定义一个计数器
for (int num = x; num <= y; num++) {
String strNum = String.valueOf(num);
boolean isPerfect = true;
char firstChar = strNum.charAt(0);
for (int i = 1; i < strNum.length(); i++) {
if (strNum.charAt(i) != firstChar) {
isPerfect = false;
break;
}
}
if (isPerfect) {
count++; // 如果是完美整数,计数器加 1
}
}
return count; // 返回计数器的值
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(1, 10) == 9);
System.out.println(solution(2, 22) == 10);
}
}
运行结果:
6、小M的多任务下载器挑战(简单)
AI调试代码:
import java.util.TreeMap;
public class Main {
public static int solution(int n, int[][] array) {
// 使用 TreeMap 来记录每个时刻正在进行的任务数量
TreeMap<Integer, Integer> taskCountAtEachSecond = new TreeMap<>();
// 遍历输入的任务数组
for (int[] task : array) {
int start = task[0];
int duration = task[1];
// 从任务开始到结束的每个时刻,任务数量加 1
for (int i = start; i < start + duration; i++) {
if (taskCountAtEachSecond.containsKey(i)) {
taskCountAtEachSecond.put(i, taskCountAtEachSecond.get(i) + 1);
} else {
taskCountAtEachSecond.put(i, 1);
}
}
}
// 找到任务数量的最大值
int maxConcurrentTasks = 0;
for (Integer count : taskCountAtEachSecond.values()) {
if (count > maxConcurrentTasks) {
maxConcurrentTasks = count;
}
}
return maxConcurrentTasks;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(2, new int[][] { { 1, 2 }, { 2, 3 } }) == 2);
System.out.println(solution(4, new int[][] { { 1, 2 }, { 2, 3 }, { 3, 5 }, { 4, 3 } }) == 3);
}
}
运行结果:
7、找单独的数(简单)
AI调试代码:
public class Main {
public static int solution(int[] inp) {
int uniqueNumber = 0; // 初始化一个变量来存储最终的结果
for (int num : inp) { // 遍历输入的数组
uniqueNumber ^= num; // 对每个数字进行异或操作
}
return uniqueNumber; // 返回最终找到的单独数字
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(new int[] { 1, 1, 2, 2, 3, 3, 4, 5, 5 }) == 4);
System.out.println(solution(new int[] { 0, 1, 0, 1, 2 }) == 2);
}
}
运行结果:
8、计算从位置 x 到 y 的最少步数(简单)
AI调试代码:
public class Main {
public static int sum(int x) {
if (x <= 0) {
return 0;
}
int res = 0;
for (int i = 1; i <= x; i++) {
res += i;
}
return res;
}
// Calculate the minimum steps from x to y
public static int solution(int x, int y) {
if (x > y) {
int temp = x;
x = y;
y = temp;
}
int l = 0, r = y - x;
int step = 0;
int stepDistance = 0;
while (l < r) {
if (step == 0) {
stepDistance = 1;
step = 1;
l += stepDistance;
continue;
}
int step1 = stepDistance + 1;
int step2 = stepDistance;
int step3 = stepDistance - 1;
if (l + step1 < r) {
int m = l + step1;
int s = sum(step1 - 1);
if ((r - m) >= s) {
l = m;
step++;
stepDistance = step1;
continue;
}
}
if (l + step2 <= r) {
int m = l + step2;
int s = sum(step2 - 1);
if ((r - m) >= s) {
l = m;
step++;
stepDistance = step2;
continue;
}
}
if (l + step3 <= r) {
int m = l + step3;
int s = sum(step3 - 1);
if ((r - m) >= s) {
l = m;
step++;
stepDistance = step3;
continue;
}
}
}
return step;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(6, 7) == 1); // Should print true
System.out.println(solution(12, 6) == 4); // Should print true
System.out.println(solution(34, 45) == 6); // Should print true
System.out.println(solution(50, 30) == 8); // Should print true
}
}
运行结果:
9、环状 DNA 序列的最小表示法(简单)
AI调试代码:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static String solution(String dna_sequence) {
// Create a list to hold the different representations of the DNA sequence
List<String> representations = new ArrayList<>();
int length = dna_sequence.length();
// Generate all rotations of the DNA sequence
for (int i = 0; i < length; i++) {
String representation = dna_sequence.substring(i) + dna_sequence.substring(0, i);
representations.add(representation);
}
// Find the minimum representation
String minRepresentation = representations.get(0);
for (String representation : representations) {
if (representation.compareTo(minRepresentation) < 0) {
minRepresentation = representation;
}
}
return minRepresentation;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution("ATCA").equals("AATC")); // Should print true
System.out.println(solution("CGAGTC").equals("AGTCCG")); // Should print true
System.out.println(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG")
.equals("AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG")); // Should print true
}
}
运行结果:
10、Base32 编码和解码问题(简单)
AI调试代码:
import java.util.ArrayList;
import java.util.List;
public class Main {
static char[] base32 = {
'9', '8', '7', '6', '5', '4', '3', '2', '1', '0',
'm', 'n', 'b', 'v', 'c', 'x', 'z', 'a', 's', 'd',
'f', 'g', 'h', 'j', 'k', 'l', 'p', 'o', 'i', 'u',
'y', 't'
};
public static String decimalToBinary8Bits(int num) {
StringBuilder binary = new StringBuilder();
for (int i = 7; i >= 0; i--) {
binary.append((num & (1 << i)) != 0 ? '1' : '0');
}
return binary.toString();
}
public static List<Integer> binaryToDecimal(String binaryStr) {
List<Integer> decimalNums = new ArrayList<>();
for (int i = 0; i < binaryStr.length(); i += 5) {
String group = binaryStr.substring(i, Math.min(i + 5, binaryStr.length()));
int decimal = 0;
for (char c : group.toCharArray()) {
decimal = decimal * 2 + (c - '0');
}
decimalNums.add(decimal);
}
return decimalNums;
}
public static String decimalArrayToBinary(List<Integer> arr) {
StringBuilder result = new StringBuilder();
for (int num : arr) {
StringBuilder binary = new StringBuilder();
for (int i = 4; i >= 0; i--) {
binary.append((num & (1 << i)) != 0 ? '1' : '0');
}
result.append(binary);
}
return result.toString();
}
public static String binaryToChar(String binaryStr) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < binaryStr.length(); i += 8) {
String group = binaryStr.substring(i, Math.min(i + 8, binaryStr.length()));
int decimal = 0;
for (char c : group.toCharArray()) {
decimal = decimal * 2 + (c - '0');
}
result.append((char) decimal);
}
return result.toString();
}
public static String jiema(String encodedStr) {
int i;
for (i = encodedStr.length() - 1; i > 0 && encodedStr.charAt(i) == '+'; i--);
String newstr = encodedStr.substring(0, i + 1);
List<Integer> st2 = new ArrayList<>();
for (char c : newstr.toCharArray()) {
for (int j = 0; j < base32.length; j++) {
if (c == base32[j]) {
st2.add(j);
}
}
}
String newnewstr = decimalArrayToBinary(st2);
String res2 = "";
if (newnewstr.length() % 40 == 10) {
String newstrs = newnewstr.substring(0, newnewstr.length() - 2);
res2 = binaryToChar(newstrs);
} else if (newnewstr.length() % 40 == 20) {
String newstrs = newnewstr.substring(0, newnewstr.length() - 4);
res2 = binaryToChar(newstrs);
} else if (newnewstr.length() % 40 == 25) {
String newstrs = newnewstr.substring(0, newnewstr.length() - 1);
res2 = binaryToChar(newstrs);
} else if (newnewstr.length() % 40 == 35) {
String newstrs = newnewstr.substring(0, newnewstr.length() - 3);
res2 = binaryToChar(newstrs);
}
return res2;
}
public static String solution(String rawStr, String encodedStr) {
List<Integer> st = new ArrayList<>();
StringBuilder str1 = new StringBuilder();
for (char c : rawStr.toCharArray()) {
str1.append(decimalToBinary8Bits(c));
}
int r = str1.length() % 40;
if (r == 8) {
str1.append("00");
} else if (r == 16) {
str1.append("0000");
} else if (r == 24) {
str1.append("0");
} else if (r == 32) {
str1.append("000");
}
st = binaryToDecimal(str1.toString());
StringBuilder res1 = new StringBuilder();
for (int value : st) {
res1.append(base32[value]);
}
while (res1.length() % 8 != 0) {
res1.append("+");
}
StringBuilder res2 = new StringBuilder();
for (int i = 0; i < encodedStr.length(); i += 8) {
res2.append(jiema(encodedStr.substring(i, Math.min(i + 8, encodedStr.length()))));
}
return res1.toString() + ":" + res2.toString();
}
public static void main(String[] args) {
// You can add more test cases here
System.out.print(solution("foo", "b0zj5+++"));
System.out.println(solution("foo", "b0zj5+++").equals("bljhy+++:bar")); // Should print true
System.out.println(solution("The encoding process represents 40-bit groups of input bits as output strings of 8 encoded characters. Proceeding from left to right, a 40-bit input group is formed by concatenating 5 8bit input groups. These 40 bits are then treated as 8 concatenated 5-bit groups, each of which is translated into a single character in the base 32 alphabet. When a bit stream is encoded via the base 32 encoding, the bit stream must be presumed to be ordered with the most-significant-bit first. That is, the first bit in the stream will be the high-order bit in the first 8bit byte, the eighth bit will be the low-order bit in the first 8bit byte, and so on.", "bljhy+++b0zj5+++").equals("maf3m164vlahyl60vlds9i6svuahmiod58l3mi6sbglhmodfcbz61b8vb0fj1162c0jjmi6d58jhb160vlk2mu89b0fj1il9b4ls9oogcak2mu89cvp25pncbuls9oo359i79lncbvjh1ln558ahzknsb4aj1lnscbj7917zc0jh3ln4bafhill9bll3yo09vashbu89cajs9id0buf21n89b5z61b8vb0fj1160vlk2mu89bul3yunz58fj3163vul3pln558a2s166vuj33knfbgj37u60vlds9v0928a3su89v4j29unf58dj5oogc8lsi17fv8sj3l093zk79kd0cals9knsbfz21p64vkz21id4b4p3ml89b4ls9c89bvjhiko8cashiknfbgs79v0vb0fj1162c0jjmi6d4zz3mkn6v9z3yla9cuf3sko158fj316fc0zhiiobb4p3ml89v4j21ol9b5z23pncbuh3m166v8zj5kn6casj5160vkz21p6458a37io459ld5168vak3zkn7bgp7i189muf3moa9b5z35pnf58lj1id4b4hs9pnd58shikoxbash116hv4zs9u61bfz35kndbfz63ba9bgj33oo5v4j3cn89caf3m167v4p79iofc0sh7o09vgpj3u89b0ss9i6sbgljmon4bzz21ol9b0ss9oosbasj5ln558ohsu6158p3zl09vgjj3u8vcvfhcod0blfh3kncczhs9kd0czz3bpnscvp7i17fv8zj1160cbh79u61bfz3bpnscvp79kd0czz3soa9caf3m16dcal3mknv58ohso6b58a3m16fv8ss9p60buf7p16xc0s3mia9b0fj1160vkz21p6458d3siddczz6zkd0czz35ynfbfh79u61bfz3mpn2v8p3z167v4p79uo0vah79kd458p3zl09vajjcn09vul31lns58a3su89v4j79u61bfz3bpnscvp79c67v4p79kdlcassk168vls79iox58jhinz+:foobar")); // Should print true
}
}
运行结果:
结语
在这篇技术博客中,小北与友友们分享了字节跳动青训营的精彩内容,从报名方式到考核内容,再到具体的算法题目示例和解答代码,让我们对青训营有了更深入的了解。通过这些实际的算法题目和解决方案,我们不仅能够学习到编程技巧,还能够感受到解决实际问题的乐趣。
希望这篇博客能够激励更多的技术爱好者参与到青训营中,提升自己的技术水平,同时小北也期待在未来能带给友友们更多有价值的技术分享~
最后,祝愿所有参与青训营的朋友们都能学有所成,技术精进,未来在技术的道路上越走越远。同时,也期待字节跳动青训营能够培养出更多的技术人才,为技术社区注入更多的活力和创新!
感谢友友们的阅读,我们下次再见~