在算法学习和刷题过程中,我们会遇到各种有趣的题目,今天就来分享三道不同类型题目的解法思路,分别是回文子串最短长度 、不相邻取数最大和 、空调遥控最佳温度区间。
一、回文子串最短长度(小红的字符串)
题目描述
小红拿到一个只包含 'a'、'b'、'c'三种字符的字符串。她想知道,这个字符串最短的、长度超过1的回文子串的长度是多少?
-
子串定义:字符串中取一段连续 的区间(例如
"abcca"的子串有"ab"、"bcca"等,但"aca"不是子串)。 -
回文定义:正着读和倒着读都相同的字符串(例如
"aa"、"aba")。 -
若不存在长度超过1的回文子串,输出
-1。
解题思路
由于字符串只包含 'a'、'b'、'c'三种字符,最短的回文子串长度只能是 2 或 3:
-
长度为 2 的回文子串:两个相同字符(如
"aa"、"bb"、"cc")。 -
长度为 3 的回文子串:首尾字符相同(如
"aba"、"bcb")。
因此,我们只需要枚举所有二元组(长度2的子串) 和三元组(长度3的子串),判断是否为回文,找到最短的那个即可。
代码实现(Python)
def shortest_palindrome(s):
n = len(s)
# 先检查所有长度为2的子串
for i in range(n - 1):
if s[i] == s[i + 1]:
return 2
# 再检查所有长度为3的子串
for i in range(n - 2):
if s[i] == s[i + 2]:
return 3
# 没有符合条件的回文子串
return -1
# 测试示例
print(shortest_palindrome("abcca")) # 输出2("cc"是回文)
print(shortest_palindrome("abcab")) # 输出-1(无长度>1的回文)
二、不相邻取数(动态规划 - 线性DP)
题目描述
小红拿到一个数组,想取一些不相邻的数,使得取出的数之和尽可能大。请帮助她求出这个最大和。
-
输入:第一行是正整数
n(数组长度),第二行是n个正整数a_i。 -
输出:不相邻数的最大和。
解题思路
这是经典的**"打家劫舍"型动态规划问题** 。设 dp[i]表示前 i个元素中,不相邻取数的最大和。
状态转移方程:
-
对于第
i个元素(i >= 2),有两种选择:-
不选第
i个元素:dp[i] = dp[i-1](继承前i-1个的最大和)。 -
选第
i个元素:dp[i] = dp[i-2] + a[i](前i-2个的最大和 + 第i个元素)。
-
-
因此,
dp[i] = max(dp[i-1], dp[i-2] + a[i])。
边界条件:
-
dp[0] = a[0](只有一个数时,最大和是它本身)。 -
dp[1] = max(a[0], a[1])(两个数时,选较大的那个)。
代码实现(Python)
def max_non_adjacent_sum(nums):
n = len(nums)
if n == 0:
return 0
if n == 1:
return nums[0]
# 初始化dp数组
dp = [0] * n
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, n):
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
return dp[-1]
# 测试示例
nums = [2, 6, 4, 1]
print(max_non_adjacent_sum(nums)) # 输出7(选6和1)
三、空调遥控(二分 / 滑动窗口)
题目描述
集训室有 n名队员,每位队员的温度诉求为 a[i]。当室内温度为 K时,若 |a[i] - K| ≤ p,队员能正常训练;否则会躁动。求最佳情况下,最多能有多少队员同时进入训练状态。
解题思路
方法一:滑动窗口(排序后)
-
排序 :将温度诉求数组
a排序,方便后续窗口操作。 -
滑动窗口 :维护一个窗口
[left, right],使得窗口内的**最大值 - 最小值 ≤ 2p *(因为|a[i]-K| ≤ p等价于K ∈ [a[i]-p, a[i]+p],所以窗口内所有数必须在同一个长度为2*p的区间内)。 -
统计最大窗口大小:窗口越大,满足条件的队员越多。
方法二:二分查找
-
排序:同样先对数组排序。
-
二分枚举答案 :假设最多能满足
k名队员,判断是否存在一个长度为k的连续子数组,其最大值 - 最小值 ≤ 2*p。 -
验证函数 :对于每个可能的
k,用二分法找是否存在这样的子数组。
代码实现(Python - 滑动窗口)
def max_trainers(a, p):
a.sort()
n = len(a)
left = 0
max_len = 0
for right in range(n):
# 收缩左边界,直到窗口内最大值-最小值 ≤ 2*p
while a[right] - a[left] > 2 * p:
left += 1
# 更新最大窗口长度
max_len = max(max_len, right - left + 1)
return max_len
# 测试示例
n, p = 6, 2
a = [1, 5, 3, 2, 4, 6]
print(max_trainers(a, p)) # 输出5(温度调为3或4时,5人满足)
总结
这三道题分别覆盖了字符串处理 、动态规划 、滑动窗口/二分查找三种经典算法思路:
-
回文子串:利用字符种类少的特性,枚举短子串。
-
不相邻取数:线性DP的典型应用(打家劫舍模型)。
-
空调遥控:排序后用滑动窗口或二分查找优化区间问题。
通过这类题目练习,可以加深对算法思路的理解,提升代码实现能力~ 🚀