文章目录
代码随想录开源LeetCode题单:代码随想录
1.LeetCode134
1.1 思路
- 核心思路:
- 总油量 vs. 总消耗:
- 如果总油量 sum(gas) >= sum(cost),则一定可以绕一圈。
- 如果总油量 sum(gas) < sum(cost),则无法绕一圈,直接返回 -1。
- 当前油量判断起点:
- 遍历过程中,维护一个变量 curr_tank,表示当前油量。
- 如果当前油量小于 0,说明从当前起点无法到达下一站,则需要重新选择起点,并重置当前油量。
- 总油量 vs. 总消耗:
- 贪心策略:
每次遇到油量不足的情况,更新起点为下一站,因为前面无法到达的加油站都不可能是有效起点。
1.2 代码
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int sum = 0;
int min = 0;
for (int i = 0; i < gas.length; i++) {
sum += (gas[i] - cost[i]);
min = Math.min(sum, min);
}
if (sum < 0) return -1;
if (min >= 0) return 0;
for (int i = gas.length - 1; i > 0; i--) {
min += (gas[i] - cost[i]);
if (min >= 0) return i;
}
return -1;
}
}
2.LeetCode135
2.1思路
双数组贪心法
- 核心问题:
- 满足条件:
- 每个孩子至少有 1 个糖果。
- 评分高的孩子比相邻评分低的孩子分得更多的糖果。
- 目标:
- 最小化糖果的总数。
- 满足条件:
- 贪心策略:
- 从左到右遍历数组:
- 如果当前孩子评分比左边高,则糖果数比左边多 1。
- 从右到左遍历数组:
- 如果当前孩子评分比右边高,则糖果数比右边多 1。
- 最终结果为两次遍历中每个孩子的最大糖果数。
- 从左到右遍历数组:
- 步骤分析:
初始化两个数组 left 和 right,分别记录从左到右和从右到左遍历时的糖果分配情况,初始值均为 1。- 第一次遍历:
从左到右遍历 ratings,如果当前评分比左边评分高,更新 left[i] = left[i-1] + 1。 - 第二次遍历:
从右到左遍历 ratings,如果当前评分比右边评分高,更新 right[i] = right[i+1] + 1。 - 计算结果:
对于每个孩子,糖果数取 max(left[i], right[i])。
- 第一次遍历:
2.2 代码
class Solution {
/**
分两个阶段
1、起点下标1 从左往右,只要 右边 比 左边 大,右边的糖果=左边 + 1
2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大
*/
public int candy(int[] ratings) {
int len = ratings.length;
int[] candyVec = new int[len];
candyVec[0] = 1;
for (int i = 1; i < len; i++) {
candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
}
for (int i = len - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) {
candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
}
}
int ans = 0;
for (int num : candyVec) {
ans += num;
}
return ans;
}
}
3.LeetCode860
3.1 思路
-
核心思想:
- 每次优先使用大面额的零钱找零(如优先使用 $10 钞票找零),以便留更多的小额零钱($5 钞票)用于后续找零。
- 模拟找零过程,判断是否能满足所有顾客的找零需求。
-
详细步骤:
- 初始化两个变量 five 和 ten 分别记录当前持有的 $5 和 $10 钞票数量。
- 遍历每一位顾客的付款金额:
- 如果顾客付 $5:无需找零,仅记录收到的 $5 钞票。
- 如果顾客付 $10:找零 $5。如果没有 $5 钞票,返回 False;否则,减少 $5 钞票数量,增加 $10 钞票数量。
- 如果顾客付 $20:优先使用 $10 和 $5 找零(找零 $15)。如果没有 $10,则使用三个 $5 钞票。如果无法找零,返回 False。
- 如果遍历完毕都能找零,返回 True。
3.2 代码
class Solution {
public boolean lemonadeChange(int[] bills) {
int five = 0;
int ten = 0;
for (int i = 0; i < bills.length; i++) {
if (bills[i] == 5) {
five++;
} else if (bills[i] == 10) {
five--;
ten++;
} else if (bills[i] == 20) {
if (ten > 0) {
ten--;
five--;
} else {
five -= 3;
}
}
if (five < 0 || ten < 0) return false;
}
return true;
}
}
4.LeetCode406
4.1 思路
-
排序规则:
- 按照身高从高到低排序,若身高相同,则按照 k 值从小到大排序:
- 身高高的人先放入队列,确保不会影响后续身高较矮的人的 k 值计算。
- 身高相同时,k 值小的人优先放入,确保队列结构正确。
- 按照身高从高到低排序,若身高相同,则按照 k 值从小到大排序:
-
队列插入:
- 按排序后的顺序依次将每个人插入队列:
- 根据每个人的 k 值,将其插入结果队列的对应位置。
- 按排序后的顺序依次将每个人插入队列:
-
为什么贪心有效:
- 身高高的人优先放置,确保后续插入时不会影响较矮的人的 k 值计算。
- 插入操作基于当前的 k 值,直接反映每个人的要求
4.2 代码
class Solution {
public int[][] reconstructQueue(int[][] people) {
// 身高从大到小排(身高相同k小的站前面)
Arrays.sort(people, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1]; // a - b 是升序排列,故在a[0] == b[0]的狀況下,會根據k值升序排列
return b[0] - a[0]; //b - a 是降序排列,在a[0] != b[0],的狀況會根據h值降序排列
});
LinkedList<int[]> que = new LinkedList<>();
for (int[] p : people) {
que.add(p[1],p); //Linkedlist.add(index, value),會將value插入到指定index裡。
}
return que.toArray(new int[people.length][]);
}
}