算法练习7

1. 字母异位词分组

题目要求将互为字母异位词的字符串放入同一组。

例如:

复制代码
["eat", "tea", "tan", "ate", "nat", "bat"]

可以分为:

复制代码
[["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]

核心思路

字母异位词中,每种字符出现的次数相同。将字符串排序后,互为异位词的字符串一定会得到同一个结果:

复制代码
"eat" -> "aet"
"tea" -> "aet"
"ate" -> "aet"

使用 HashMap

复制代码
key:排序后的字符串
value:具有相同 key 的原字符串列表

复杂度

设字符串平均长度为 k,字符串数量为 n

复制代码
时间复杂度:O(n × k log k)
空间复杂度:O(n × k)

2. 环形链表

判断一个链表中是否存在环。

复制代码
3 -> 2 -> 0 -> -4
     ^         |
     |_________|

核心思路:快慢指针

定义两个指针:

复制代码
slow:每次走 1 步
fast:每次走 2 步
  • 无环:fast 最终会到达 null

  • 有环:fast 会在环中追上 slow,两个指针会指向同一个节点。

    while (fast != null && fast.next != null) {
    slow = slow.next;
    fast = fast.next.next;

    复制代码
      if (slow == fast) {
          return true;
      }

    }

复杂度

复制代码
时间复杂度:O(n)
空间复杂度:O(1)

3. 最长回文子串

在字符串中找到最长的回文子串。

复制代码
输入:"babad"
输出:"bab" 或 "aba"

输入:"cbbd"
输出:"bb"

核心思路:中心扩展

回文串有两种中心:

复制代码
奇数长度:"aba"
中心是 b

偶数长度:"abba"
中心在两个 b 之间

因此每个位置都需要尝试两次扩展:

复制代码
expandAroundCenter(s, i, i);       // 奇数长度
expandAroundCenter(s, i, i + 1);   // 偶数长度

扩展条件:

复制代码
left >= 0
right < s.length()
s.charAt(left) == s.charAt(right)

起始下标计算

当回文长度为 len,当前左中心为 i 时:

复制代码
start = i - (len - 1) / 2;

这条公式能统一处理奇数长度与偶数长度回文。

复杂度

复制代码
时间复杂度:O(n²)
空间复杂度:O(1)

4. 零钱兑换

给定硬币面额 coins 和金额 amount,求凑出目标金额所需的最少硬币数。无法凑出时返回 -1

复制代码
coins = [1, 2, 5]
amount = 11

答案:3
解释:5 + 5 + 1

为什么不能贪心

复制代码
coins = [1, 3, 4]
amount = 6

贪心:4 + 1 + 1,需要 3 枚
最优:3 + 3,只需要 2 枚

因此不能只优先选择面额最大的硬币。

核心思路:一维动态规划

定义:

复制代码
dp[x]:凑出金额 x 所需的最少硬币数量

初始状态:

复制代码
dp[0] = 0;

其他位置先初始化为不可能达到的大值:

复制代码
Arrays.fill(dp, amount + 1);

状态转移:

复制代码
dp[currentAmount] = Math.min(
    dp[currentAmount],
    dp[currentAmount - coin] + 1
);

含义是:最后选择一枚 coin 后,前面先凑出 currentAmount - coin

复杂度

复制代码
时间复杂度:O(amount × coins.length)
空间复杂度:O(amount)

5. 买卖股票的最佳时机

只能买入一次、卖出一次,求最大利润。

复制代码
prices = [7, 1, 5, 3, 6, 4]
答案:5

第 2 天以 1 买入,第 5 天以 6 卖出。

核心思路:维护历史最低价格

遍历每一天的股价时,维护:

复制代码
minPrice:截至当前日期的最低买入价格
maxProfit:截至当前日期的最大利润

for (int price : prices) {
    minPrice = Math.min(minPrice, price);
    maxProfit = Math.max(maxProfit, price - minPrice);
}

当出现一个更低价格时,它将成为后续更好的买入机会;当前价格则可以尝试作为卖出价格。

复杂度

复制代码
时间复杂度:O(n)
空间复杂度:O(1)

6. 除自身以外数组的乘积

返回数组 answer,其中:

复制代码
answer[i] = 除 nums[i] 外其余元素的乘积

输入:[1, 2, 3, 4]
输出:[24, 12, 8, 6]

核心思路:前缀积 + 后缀积

定义:

复制代码
left[i]:i 左边所有元素的乘积
right[i]:i 右边所有元素的乘积

因此:

复制代码
answer[i] = left[i] × right[i]

例如:

复制代码
nums  = [1, 2, 3, 4]
left  = [1, 1, 2, 6]
right = [24, 12, 4, 1]

answer = [24, 12, 8, 6]

边界位置:

复制代码
left[0] = 1;
right[n - 1] = 1;

因为没有元素参与相乘时,乘积定义为 1

复杂度

复制代码
时间复杂度:O(n)
空间复杂度:O(n)

还可以进一步优化为:将前缀积直接存入 answer,再用一个变量从右向左累乘后缀积,从而将额外空间优化到 O(1)


7. 最大子数组和

找到一个和最大的连续子数组。

复制代码
输入:[-2, 1, -3, 4, -1, 2, 1, -5, 4]
输出:6

最大连续子数组:[4, -1, 2, 1]

核心思路:Kadane 算法

不断累加当前连续子数组的和:

  • 当前累计和大于等于 0:继续保留;

  • 当前累计和小于 0:它会拖累后续结果,直接丢弃,从后续元素重新开始。

    int currentSum = 0;
    int maxSum = nums[0];

    for (int num : nums) {
    currentSum += num;
    maxSum = Math.max(maxSum, currentSum);

    复制代码
      if (currentSum < 0) {
          currentSum = 0;
      }

    }

为什么不能把 maxSum 初始化为 0

对于全负数数组:

复制代码
[-3, -2, -5]

最大连续子数组和应该是:

复制代码
-2

若初始化为 0,会错误返回 0

复杂度

复制代码
时间复杂度:O(n)
空间复杂度:O(1)

8. 合并区间

将所有重叠区间合并。

复制代码
输入:[[1,3], [2,6], [8,10], [15,18]]
输出:[[1,6], [8,10], [15,18]]

核心思路:排序 + 贪心扫描

先按区间左端点排序:

复制代码
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);

然后依次判断当前区间是否和结果中最后一个区间重叠。

判断条件:

复制代码
lastEnd < currentStart
  • 若成立:不重叠,直接加入结果;

  • 否则:发生重叠,更新右端点。

    lastEnd = Math.max(lastEnd, currentEnd);

端点相接也需要合并

复制代码
[1, 4] 和 [4, 5]

两者在端点 4 相接,结果应为:

复制代码
[1, 5]

因此"不重叠"的条件必须是:

复制代码
lastEnd < currentStart

而不能写成:

复制代码
lastEnd <= currentStart

复杂度

复制代码
排序:O(n log n)
扫描:O(n)
总时间复杂度:O(n log n)
空间复杂度:O(n)
相关推荐
掉鱼的猫1 小时前
跳出 Fatjar 的束缚:Solon 插件的体外扩展(E-Spi)与热插拔(H-Spi)
java
可编程芯片开发2 小时前
基于模糊PID控制的六步逆变器供电无刷直流电机调速simulink仿真
算法
Bill FANG2 小时前
从原生Java NIO到Netty重构:充电桩Socket服务端高性能改造实战
java·重构·nio
2601_955759412 小时前
Claude API 成本审计:该看哪些指标,怎么分析更靠谱
java
带刺的坐椅2 小时前
跳出 Fatjar 的束缚:Solon 插件的体外扩展(E-Spi)与热插拔(H-Spi)
java·jar·solon·plugin·fatjar
宁之明起(B服)2 小时前
Java 反序列化漏洞-xmldecoder/SnakeYAM
java·开发语言
imperialeast2 小时前
WinAXP音乐播放器8月4日更新
windows·算法·ui
ZhouDevin2 小时前
算法论文/模型微调1——CNN架构做lora微调训练
人工智能·深度学习·算法·架构·cnn
禾高网络2 小时前
开启环保新潮流:回收小程序系统功能介绍
java·大数据·小程序