# 手撕代码
# Python
# 1. 反转一个字符串
def reverse_string(s):
return s[::-1]
# 测试用例
print(reverse_string("hello")) # 输出: "olleh"
print(reverse_string("")) # 输出: ""
2
3
4
5
6
答案: 使用切片 [::-1] 是最高效和Pythonic的方式。它从字符串的末尾开始,步长为-1,直到字符串的开头,从而实现反转。
# 2. 判断一个字符串是否是回文
def is_palindrome(s):
# 处理大小写和空格,例如 "A man a plan a canal Panama"
s = ''.join(char.lower() for char in s if char.isalnum())
return s == s[::-1]
# 测试用例
print(is_palindrome("radar")) # 输出: True
print(is_palindrome("hello")) # 输出: False
print(is_palindrome("A man a plan a canal Panama")) # 输出: True
2
3
4
5
6
7
8
9
答案: 核心思想是处理后的字符串(仅保留字母数字并转为小写)是否与其反转字符串相等。
# 3. 计算斐波那契数列第n项(使用递归和循环两种方法)
方法一:循环(高效,推荐)
def fibonacci_iterative(n):
if n <= 1:
return n
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, a + b
return b
# 测试用例
print(fibonacci_iterative(10)) # 输出: 55
2
3
4
5
6
7
8
9
10
方法二:递归(低效,但考察算法思想)
def fibonacci_recursive(n):
if n <= 1:
return n
return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)
# 测试用例
print(fibonacci_recursive(10)) # 输出: 55
2
3
4
5
6
7
答案: 面试中通常希望看到循环方法,因为它的时间复杂度是O(n),而递归是O(2^n)。但可能要求写出递归版本并分析其缺点。
# 4. 找出列表中的重复元素
def find_duplicates(lst):
seen = set()
duplicates = set()
for item in lst:
if item in seen:
duplicates.add(item)
else:
seen.add(item)
return list(duplicates)
# 测试用例
print(find_duplicates([1, 2, 3, 2, 1, 5, 6, 5, 5, 5])) # 输出: [1, 2, 5]
2
3
4
5
6
7
8
9
10
11
12
答案: 使用一个集合 seen 来跟踪已经遇到过的元素。如果一个元素已经在 seen 中,则将其添加到 duplicates 集合中(使用集合自动去重)。
# 5. 统计列表中每个元素的出现次数
from collections import Counter
def count_frequency(lst):
return dict(Counter(lst))
# 测试用例
print(count_frequency(['a', 'b', 'a', 'c', 'b', 'a'])) # 输出: {'a': 3, 'b': 2, 'c': 1}
2
3
4
5
6
7
答案: collections.Counter 是专门为此目的设计的工具,非常高效和简洁。也可以使用字典自己实现:frequency = {}; for item in lst: frequency[item] = frequency.get(item, 0) + 1。
# 6. 实现一个装饰器,计算函数的执行时间
import time
import functools
def timer(func):
@functools.wraps(func) # 保留原函数的元信息
def wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = func(*args, **kwargs)
end_time = time.perf_counter()
print(f"函数 {func.__name__} 运行耗时: {end_time - start_time:.4f} 秒")
return result
return wrapper
@timer
def example_function(n):
time.sleep(n)
return "Done"
# 测试用例
example_function(2)
# 输出: 函数 example_function 运行耗时: 2.00xx 秒
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
答案: 这是一个装饰器的经典用例。@functools.wraps 是一个好习惯,它确保被装饰的函数保留其名称和文档字符串。time.perf_counter() 提供了最高精度的计时。
# 7. 写一个函数,检查传入的文件路径是否存在,如果存在则读取文件内容
import os
def read_file_safely(file_path):
if not os.path.exists(file_path):
return f"错误:文件 {file_path} 不存在。"
try:
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
return content
except Exception as e:
return f"读取文件时发生错误: {e}"
# 测试用例(需要准备一个 test.txt 文件)
print(read_file_safely("test.txt"))
print(read_file_safely("nonexistent_file.txt"))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
答案: 这道题考察文件操作和异常处理。先检查路径是否存在是第一步,但使用 with open 并捕获可能的异常(如编码错误)同样重要,这体现了代码的健壮性。
# 8. 对字典列表进行排序(根据某个共同的键)
def sort_dict_list(lst, key):
return sorted(lst, key=lambda x: x[key])
# 测试用例
data = [
{'name': 'Alice', 'age': 25},
{'name': 'Bob', 'age': 30},
{'name': 'Charlie', 'age': 22}
]
print(sort_dict_list(data, 'age'))
# 输出: [{'name': 'Charlie', 'age': 22}, {'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]
2
3
4
5
6
7
8
9
10
11
答案: sorted() 函数的 key 参数非常强大,它接受一个函数来指定排序的依据。这里使用 lambda 函数从每个字典中提取出指定的键的值作为排序键。
# 9. 合并两个字典
def merge_dicts(dict1, dict2):
# 在Python 3.5+中,可以使用 ** 操作符解包
return {**dict1, **dict2}
# 另一种方式(更新dict1)
# def merge_dicts(dict1, dict2):
# dict1.update(dict2)
# return dict1
# 测试用例
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
print(merge_dicts(d1, d2)) # 输出: {'a': 1, 'b': 3, 'c': 4}
2
3
4
5
6
7
8
9
10
11
12
13
答案: {**dict1, **dict2} 是Python 3.5+引入的最简洁的方法。如果键有冲突,后者(dict2)的值会覆盖前者(dict1)的值。
# 10. 列表推导式:将一个列表中的整数转换为字符串,并过滤掉偶数
def convert_and_filter(lst):
return [str(x) for x in lst if x % 2 != 0]
# 测试用例
print(convert_and_filter([1, 2, 3, 4, 5, 6])) # 输出: ['1', '3', '5']
2
3
4
5
答案: 列表推导式是Python的核心特性,可以简洁地实现map和filter操作。if x % 2 != 0 是过滤条件,str(x) 是转换操作。
# 11. 实现一个上下文管理器,用于文件操作
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode, encoding='utf-8')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# 如果返回True,则不会抛出异常。返回None或False则会抛出。
# 这里我们选择不处理异常,让其正常抛出
return False
# 测试用例
with FileManager('test.txt', 'w') as f:
f.write("Hello, Context Manager!")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
答案: 上下文管理器通过 __enter__ 和 __exit__ 两个魔法方法实现。with 语句会自动管理资源的获取和释放(如打开和关闭文件),即使发生异常也能保证 __exit__ 方法被调用,从而避免资源泄漏。
# 12. 使用递归列出目录下的所有文件(考察os.walk)
import os
def list_files_recursively(directory):
file_list = []
for root, dirs, files in os.walk(directory):
for file in files:
# 连接根目录和文件名,形成完整路径
file_path = os.path.join(root, file)
file_list.append(file_path)
return file_list
# 测试用例
files = list_files_recursively('.') # 列出当前目录下所有文件
for f in files[:5]: # 打印前5个
print(f)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
答案: os.walk(directory) 是遍历目录树的标准方法,它返回一个生成器,每次产生一个三元组 (当前文件夹路径, 子文件夹列表, 文件列表)。这比手动写递归要简单和安全得多。
# 13. 计算一个数的阶乘
def factorial(n):
if n < 0:
raise ValueError("阶乘只能计算非负整数。")
result = 1
for i in range(1, n + 1):
result *= i
return result
# 测试用例
print(factorial(5)) # 输出: 120
print(factorial(0)) # 输出: 1
2
3
4
5
6
7
8
9
10
11
答案: 使用循环是计算阶乘最有效的方式。注意处理边界情况:n=0 时结果为1,n为负数时应该抛出异常。
# 14. 过滤出列表中的所有偶数
def filter_even_numbers(lst):
return list(filter(lambda x: x % 2 == 0, lst))
# 或者使用列表推导式: [x for x in lst if x % 2 == 0]
# 测试用例
print(filter_even_numbers([1, 2, 3, 4, 5, 6, 7, 8])) # 输出: [2, 4, 6, 8]
2
3
4
5
6
答案: 展示了 filter 函数的使用,它接受一个函数和一个可迭代对象,并返回一个迭代器,其中包含使函数返回True的所有元素。列表推导式是更Pythonic的替代方案。
# 15. 将两个列表合并为一个字典(一个列表为键,另一个为值)
def lists_to_dict(keys, values):
return dict(zip(keys, values))
# 测试用例
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'New York']
print(lists_to_dict(keys, values))
# 输出: {'name': 'Alice', 'age': 25, 'city': 'New York'}
2
3
4
5
6
7
8
答案: zip(keys, values) 将两个列表“压缩”成一个可迭代对象,其中每个元素都是一个 (key, value) 元组。dict() 函数可以直接接受这种元组序列来创建字典。
# 16. 实现一个简单的队列(FIFO)类
class Queue:
def __init__(self):
self.items = []
def is_empty(self):
return len(self.items) == 0
def enqueue(self, item):
self.items.insert(0, item) # 在列表头部插入,尾部就是队首
def dequeue(self):
if not self.is_empty():
return self.items.pop() # 从列表尾部弹出
else:
raise IndexError("从空队列中出队")
def size(self):
return len(self.items)
# 测试用例
q = Queue()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
print(q.dequeue()) # 输出: 1
print(q.dequeue()) # 输出: 2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
答案: 使用列表模拟队列。enqueue(入队)在列表头部(index=0)插入元素,dequeue(出队)从列表尾部弹出元素。注意检查队列是否为空。
# 17. 去除字符串首尾的空格(不能使用str.strip())
def custom_strip(s):
start = 0
end = len(s) - 1
# 找到第一个非空格字符的索引
while start <= end and s[start] == ' ':
start += 1
# 找到最后一个非空格字符的索引
while end >= start and s[end] == ' ':
end -= 1
return s[start:end+1]
# 测试用例
print(custom_strip(" hello world ")) # 输出: "hello world"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
答案: 手动实现 strip() 功能。通过两个循环分别找到字符串开头和末尾非空格字符的索引,然后使用切片返回中间的部分。
# 18. 计算字符串中元音字母的个数
def count_vowels(s):
vowels = "aeiouAEIOU"
count = 0
for char in s:
if char in vowels:
count += 1
return count
# 测试用例
print(count_vowels("Hello World")) # 输出: 3 (e, o, o)
2
3
4
5
6
7
8
9
10
答案: 遍历字符串中的每个字符,检查它是否存在于元音字符串中。注意要同时包含大小写字母。
# 19. 将一段文本拆分成单词,并统计每个单词的出现次数
from collections import Counter
import re
def word_count(text):
# 使用正则表达式找到所有单词(忽略标点)
words = re.findall(r'\b\w+\b', text.lower())
return dict(Counter(words))
# 测试用例
text = "Hello world, hello Python! World of Python."
print(word_count(text))
# 输出: {'hello': 2, 'world': 2, 'python': 2, 'of': 1}
2
3
4
5
6
7
8
9
10
11
12
答案: 使用正则表达式 r'\b\w+\b' 可以很好地处理单词边界和标点符号。text.lower() 将所有文本转为小写,确保 "Hello" 和 "hello" 被算作同一个单词。
# 20. 使用生成器实现一个斐波那契数列
def fibonacci_generator():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 测试用例
fib_gen = fibonacci_generator()
for _ in range(10):
print(next(fib_gen), end=" ")
# 输出: 0 1 1 2 3 5 8 13 21 34
2
3
4
5
6
7
8
9
10
11
答案: 生成器使用 yield 关键字,它可以产生一个值并暂停函数执行,下次调用时从暂停处继续。这对于生成无限序列(如斐波那契数列)非常高效,因为它不会一次性计算所有值并存储在内存中。
# Java
好的,以下是20道针对软件测试工程师岗位的Java数组和字符串高频手撕代码面试题及其答案。
# 1. 反转字符串
public String reverseString(String str) {
if (str == null || str.length() <= 1) {
return str;
}
return new StringBuilder(str).reverse().toString();
}
// 测试用例
// System.out.println(reverseString("hello")); // 输出: "olleh"
// System.out.println(reverseString("")); // 输出: ""
// System.out.println(reverseString(null)); // 输出: null
2
3
4
5
6
7
8
9
10
11
# 2. 判断字符串是否是回文
public boolean isPalindrome(String str) {
if (str == null) return false;
str = str.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
int left = 0, right = str.length() - 1;
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
// 测试用例
// System.out.println(isPalindrome("A man, a plan, a canal: Panama")); // true
// System.out.println(isPalindrome("race a car")); // false
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 3. 找出数组中第二大的数
public int findSecondLargest(int[] arr) {
if (arr == null || arr.length < 2) {
throw new IllegalArgumentException("数组长度至少为2");
}
int first = Integer.MIN_VALUE;
int second = Integer.MIN_VALUE;
for (int num : arr) {
if (num > first) {
second = first;
first = num;
} else if (num > second && num != first) {
second = num;
}
}
if (second == Integer.MIN_VALUE) {
throw new IllegalArgumentException("没有第二大的数");
}
return second;
}
// 测试用例
// System.out.println(findSecondLargest(new int[]{12, 35, 1, 10, 34, 1})); // 34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 4. 找出数组中缺失的最小正整数
public int firstMissingPositive(int[] nums) {
int n = nums.length;
// 第一次遍历,将每个正整数放到正确的位置上
for (int i = 0; i < n; i++) {
while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
int temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
}
}
// 第二次遍历,找到第一个位置不正确的数
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
return n + 1;
}
// 测试用例
// System.out.println(firstMissingPositive(new int[]{1, 2, 0})); // 3
// System.out.println(firstMissingPositive(new int[]{3, 4, -1, 1})); // 2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 5. 合并两个有序数组
public void mergeSortedArrays(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k--] = nums1[i--];
} else {
nums1[k--] = nums2[j--];
}
}
while (j >= 0) {
nums1[k--] = nums2[j--];
}
}
// 测试用例
// int[] nums1 = new int[]{1, 2, 3, 0, 0, 0};
// int[] nums2 = new int[]{2, 5, 6};
// mergeSortedArrays(nums1, 3, nums2, 3);
// System.out.println(Arrays.toString(nums1)); // [1, 2, 2, 3, 5, 6]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 6. 字符串转换为整数 (atoi)
public int myAtoi(String s) {
if (s == null || s.length() == 0) return 0;
int index = 0, sign = 1, total = 0;
// 去除前导空格
while (index < s.length() && s.charAt(index) == ' ') {
index++;
}
if (index == s.length()) return 0;
// 处理符号
if (s.charAt(index) == '+' || s.charAt(index) == '-') {
sign = s.charAt(index) == '+' ? 1 : -1;
index++;
}
// 转换数字
while (index < s.length()) {
int digit = s.charAt(index) - '0';
if (digit < 0 || digit > 9) break;
// 检查溢出
if (Integer.MAX_VALUE / 10 < total ||
(Integer.MAX_VALUE / 10 == total && Integer.MAX_VALUE % 10 < digit)) {
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
total = total * 10 + digit;
index++;
}
return total * sign;
}
// 测试用例
// System.out.println(myAtoi("42")); // 42
// System.out.println(myAtoi(" -42")); // -42
// System.out.println(myAtoi("4193 with words")); // 4193
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 7. 找出数组中重复的数字
public int findDuplicate(int[] nums) {
// 使用龟兔赛跑算法(Floyd循环检测)
int slow = nums[0];
int fast = nums[0];
do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);
// 找到循环的入口点
slow = nums[0];
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
// 测试用例
// System.out.println(findDuplicate(new int[]{1, 3, 4, 2, 2})); // 2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 8. 无重复字符的最长子串
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) return 0;
int maxLength = 0;
Map<Character, Integer> map = new HashMap<>();
for (int left = 0, right = 0; right < s.length(); right++) {
char currentChar = s.charAt(right);
if (map.containsKey(currentChar)) {
left = Math.max(left, map.get(currentChar) + 1);
}
map.put(currentChar, right);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
// 测试用例
// System.out.println(lengthOfLongestSubstring("abcabcbb")); // 3
// System.out.println(lengthOfLongestSubstring("bbbbb")); // 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 9. 两数之和
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), i};
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
// 测试用例
// System.out.println(Arrays.toString(twoSum(new int[]{2, 7, 11, 15}, 9))); // [0, 1]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 10. 旋转数组
public void rotate(int[] nums, int k) {
if (nums == null || nums.length == 0) return;
k = k % nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
private void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
// 测试用例
// int[] nums = new int[]{1, 2, 3, 4, 5, 6, 7};
// rotate(nums, 3);
// System.out.println(Arrays.toString(nums)); // [5, 6, 7, 1, 2, 3, 4]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 11. 验证括号有效性
public boolean isValid(String s) {
if (s == null || s.length() % 2 != 0) return false;
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(') {
stack.push(')');
} else if (c == '[') {
stack.push(']');
} else if (c == '{') {
stack.push('}');
} else if (stack.isEmpty() || stack.pop() != c) {
return false;
}
}
return stack.isEmpty();
}
// 测试用例
// System.out.println(isValid("()[]{}")); // true
// System.out.println(isValid("([)]")); // false
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 12. 寻找数组中的峰值
public int findPeakElement(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < nums[mid + 1]) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
// 测试用例
// System.out.println(findPeakElement(new int[]{1, 2, 3, 1})); // 2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 13. 最长公共前缀
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++) {
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.isEmpty()) return "";
}
}
return prefix;
}
// 测试用例
// System.out.println(longestCommonPrefix(new String[]{"flower", "flow", "flight"})); // "fl"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 14. 移动零到数组末尾
public void moveZeroes(int[] nums) {
if (nums == null || nums.length == 0) return;
int nonZeroIndex = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[nonZeroIndex++] = nums[i];
}
}
for (int i = nonZeroIndex; i < nums.length; i++) {
nums[i] = 0;
}
}
// 测试用例
// int[] nums = new int[]{0, 1, 0, 3, 12};
// moveZeroes(nums);
// System.out.println(Arrays.toString(nums)); // [1, 3, 12, 0, 0]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 15. 字符串的排列检查
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length()) return false;
int[] s1Count = new int[26];
int[] s2Count = new int[26];
for (int i = 0; i < s1.length(); i++) {
s1Count[s1.charAt(i) - 'a']++;
s2Count[s2.charAt(i) - 'a']++;
}
for (int i = 0; i < s2.length() - s1.length(); i++) {
if (matches(s1Count, s2Count)) return true;
s2Count[s2.charAt(i) - 'a']--;
s2Count[s2.charAt(i + s1.length()) - 'a']++;
}
return matches(s1Count, s2Count);
}
private boolean matches(int[] s1Count, int[] s2Count) {
for (int i = 0; i < 26; i++) {
if (s1Count[i] != s2Count[i]) return false;
}
return true;
}
// 测试用例
// System.out.println(checkInclusion("ab", "eidbaooo")); // true
// System.out.println(checkInclusion("ab", "eidboaoo")); // false
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 16. 最大子数组和
public int maxSubArray(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int maxSoFar = nums[0];
int maxEndingHere = nums[0];
for (int i = 1; i < nums.length; i++) {
maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]);
maxSoFar = Math.max(maxSoFar, maxEndingHere);
}
return maxSoFar;
}
// 测试用例
// System.out.println(maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4})); // 6
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 17. 寻找旋转排序数组中的最小值
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[right]) {
left = mid + 1;
} else {
right = mid;
}
}
return nums[left];
}
// 测试用例
// System.out.println(findMin(new int[]{3, 4, 5, 1, 2})); // 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 18. 有效的字母异位词
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
int[] counter = new int[26];
for (int i = 0; i < s.length(); i++) {
counter[s.charAt(i) - 'a']++;
counter[t.charAt(i) - 'a']--;
}
for (int count : counter) {
if (count != 0) return false;
}
return true;
}
// 测试用例
// System.out.println(isAnagram("anagram", "nagaram")); // true
// System.out.println(isAnagram("rat", "car")); // false
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 19. 矩阵置零
public void setZeroes(int[][] matrix) {
if (matrix == null || matrix.length == 0) return;
boolean firstRowZero = false;
boolean firstColZero = false;
// 检查第一行是否有零
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[0][j] == 0) {
firstRowZero = true;
break;
}
}
// 检查第一列是否有零
for (int i = 0; i < matrix.length; i++) {
if (matrix[i][0] == 0) {
firstColZero = true;
break;
}
}
// 使用第一行和第一列标记零的位置
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < matrix[0].length; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// 根据标记设置零
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < matrix[0].length; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
// 处理第一行
if (firstRowZero) {
for (int j = 0; j < matrix[0].length; j++) {
matrix[0][j] = 0;
}
}
// 处理第一列
if (firstColZero) {
for (int i = 0; i < matrix.length; i++) {
matrix[i][0] = 0;
}
}
}
// 测试用例
// int[][] matrix = {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}};
// setZeroes(matrix);
// System.out.println(Arrays.deepToString(matrix)); // [[1, 0, 1], [0, 0, 0], [1, 0, 1]]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 20. 字符串相乘
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) return "0";
int m = num1.length(), n = num2.length();
int[] result = new int[m + n];
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
int product = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
int sum = product + result[i + j + 1];
result[i + j + 1] = sum % 10;
result[i + j] += sum / 10;
}
}
StringBuilder sb = new StringBuilder();
for (int digit : result) {
if (!(sb.length() == 0 && digit == 0)) {
sb.append(digit);
}
}
return sb.length() == 0 ? "0" : sb.toString();
}
// 测试用例
// System.out.println(multiply("2", "3")); // "6"
// System.out.println(multiply("123", "456")); // "56088"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29