#leetcode# 、

#leetcode#

1318.或运算的最小翻转次数

/**

* 解决方案类:解决 LeetCode 1318. 或运算的最小翻转次数问题

* 问题描述:给定三个正整数 a、b、c,你可以对 a 或 b 的二进制位进行翻转操作(0 变 1,1 变 0),

* 要求使得 a | b == c 成立,计算最少需要多少次翻转操作。

* 核心思路:

* 逐位分析二进制位的要求,根据 c 的当前位是 0 或 1,分别计算 a、b 对应位需要的翻转次数,累加得到总次数;

* 时间复杂度 O(1)(固定遍历 31 位二进制位,常数级操作),

* 空间复杂度 O(1)(仅使用常数级变量)。

*/

public class Solution {

/**

* 计算使 a | b == c 成立的最小翻转次数

* @param a 第一个整数

* @param b 第二个整数

* @param c 目标结果整数

* @return 最少翻转次数

*/

public int minFlips(int a, int b, int c) {

int ans = 0; // 累计翻转次数

// 遍历 32 位整数的低 31 位(题目中数值为正整数,最高位为0,无需处理)

for (int i = 0; i < 31; ++i) {

// 提取 a 的第 i 位二进制值(0 或 1):右移 i 位后与 1 按位与,仅保留第 i 位

int bitA = (a >> i) & 1;

// 提取 b 的第 i 位二进制值

int bitB = (b >> i) & 1;

// 提取 c 的第 i 位二进制值

int bitC = (c >> i) & 1;

if (bitC == 0) {

// 情况1:c 的第 i 位为 0

// 要求 a | b 的第 i 位为 0 → a 和 b 的第 i 位必须都为 0

// 翻转次数 = a的第i位(1则需翻转,0则无需) + b的第i位(同理)

ans += bitA + bitB;

} else {

// 情况2:c 的第 i 位为 1

// 要求 a | b 的第 i 位为 1 → a 或 b 的第 i 位至少一个为 1

// 若两者都为 0,需翻转其中一个(次数+1);否则无需翻转(次数+0)

ans += (bitA + bitB == 0) ? 1 : 0;

}

}

return ans;

}

}

1268.搜索推荐系统

/**

* 解决方案类:解决 LeetCode 1268. 搜索推荐系统问题

* 问题描述:给定产品数组 products 和搜索词 searchWord,

* 对于 searchWord 的每个前缀(第1个字符、前2个字符...前n个字符),

* 返回最多3个按字典序排序的、以该前缀开头的产品推荐列表;

* 核心思路:

* 字典树(Trie)+ 最大堆:

* 1. 字典树存储所有产品的字符前缀,每个节点维护一个最多3个元素的最大堆;

* 2. 插入产品时,每个字符节点的堆存储以该前缀开头的产品,超出3个则移除最大的(保证堆中是最小的3个);

* 3. 查询时遍历搜索词前缀,从对应节点的堆中取出元素并反转(转为升序);

* 时间复杂度 O(m*L + n*L)(m=产品数,L=产品平均长度;n=搜索词长度),

* 空间复杂度 O(m*L)(字典树存储所有产品的字符)。

*/

// 字典树节点类:每个节点包含子节点映射和存储最多3个单词的最大堆

class TrieNode {

// 子节点映射:key=字符,value=该字符对应的子节点

Map<Character, TrieNode> child = new HashMap<>();

// 最大堆:存储以当前前缀开头的单词,自定义比较器实现「字典序降序」(Java默认最小堆)

// 堆中最多保留3个元素,保证是字典序最小的3个(移除最大的)

PriorityQueue<String> words = new PriorityQueue<>((a, b) -> b.compareTo(a));

}

public class Solution {

/**

* 向字典树中插入单个单词

* @param root 字典树根节点

* @param word 待插入的产品单词

*/

private void addWord(TrieNode root, String word) {

TrieNode cur = root; // 从根节点开始遍历

// 遍历单词的每个字符,构建字典树路径

for (char ch : word.toCharArray()) {

// 若当前字符的子节点不存在,创建新节点

if (!cur.child.containsKey(ch)) {

cur.child.put(ch, new TrieNode());

}

// 移动到当前字符的子节点

cur = cur.child.get(ch);

// 将单词加入当前节点的最大堆

cur.words.offer(word);

// 堆中元素超过3个时,移除字典序最大的元素(保证堆中仅保留最小的3个)

if (cur.words.size() > 3) {

cur.words.poll();

}

}

}

/**

* 生成搜索词每个前缀的推荐产品列表

* @param products 产品数组

* @param searchWord 搜索词

* @return 每个前缀对应的推荐列表(最多3个,升序)

*/

public List<List<String>> suggestedProducts(String[] products, String searchWord) {

// 初始化字典树根节点

TrieNode root = new TrieNode();

// 将所有产品插入字典树

for (String word : products) {

addWord(root, word);

}

List<List<String>> ans = new ArrayList<>(); // 最终结果列表

TrieNode cur = root; // 从根节点开始遍历搜索词

boolean flag = false; // 标记:是否已无匹配的前缀(后续前缀直接返回空列表)

// 遍历搜索词的每个字符(逐个构建前缀)

for (char ch : searchWord.toCharArray()) {

// 情况1:已无匹配前缀 或 当前字符无对应子节点 → 该前缀无推荐,添加空列表

if (flag || !cur.child.containsKey(ch)) {

ans.add(new ArrayList<>());

flag = true; // 标记后续前缀均无匹配

} else {

// 情况2:当前字符有对应子节点 → 移动到该子节点

cur = cur.child.get(ch);

List<String> selects = new ArrayList<>();

// 取出堆中所有元素(最多3个,字典序降序)

while (!cur.words.isEmpty()) {

selects.add(cur.words.poll());

}

// 反转列表:将降序转为升序(符合题目要求的字典序)

Collections.reverse(selects);

// 将该前缀的推荐列表加入结果

ans.add(selects);

}

}

return ans;

}

}

435.无重叠区间

class Solution {

/**

* 题目:无重叠区间(最少移除多少区间使剩余区间无重叠)

* 核心思路(贪心解法,最优解):

* 1. 贪心策略:优先选择「结束时间最早」的区间,尽可能为后续区间留出更多空间

* 2. 问题转化:最少移除数 = 总区间数 - 最大不重叠区间数(与动态规划思路一致,但贪心效率更高)

* 3. 排序规则:按区间右端点升序排序(核心!保证每次选的是结束最早的区间)

* 时间复杂度:O(n log n)(排序 O(n log n) + 一次遍历 O(n))

* 空间复杂度:O(log n)(排序的系统栈空间)

*

* @param intervals 二维数组,每个元素为 [左端点, 右端点] 的区间

* @return 最少需要移除的区间数量

*/

public int eraseOverlapIntervals(int[][] intervals) {

// 边界条件:无区间时,无需移除任何区间

if (intervals.length == 0) {

return 0;

}

// 步骤1:按区间「右端点」升序排序(贪心策略的核心前提)

// 排序后,前面的区间结束更早,优先选这类区间能最大化不重叠区间的数量

Arrays.sort(intervals, new Comparator<int[]>() {

public int compare(int[] interval1, int[] interval2) {

// 右端点升序:interval1[1] - interval2[1] 为正则 interval1 在后,负则在前

return interval1[1] - interval2[1];

}

});

int n = intervals.length;

// 步骤2:初始化贪心遍历的关键变量

int right = intervals[0][1]; // 记录当前选中区间的右端点(初始为第一个区间的右端点)

int ans = 1; // 记录最大不重叠区间数(初始为1,因为至少选第一个区间)

// 步骤3:遍历剩余区间,统计最大不重叠区间数

for (int i = 1; i < n; ++i) {

// 关键判断:当前区间的左端点 >= 上一个选中区间的右端点 → 无重叠,可选中

if (intervals[i][0] >= right) {

++ans; // 不重叠区间数+1

right = intervals[i][1];// 更新选中区间的右端点为当前区间的右端点

}

// 若当前区间与上一个选中区间重叠 → 直接跳过(贪心策略:不选这个重叠区间,保留结束更早的那个)

}

// 步骤4:计算最少移除数 = 总区间数 - 最大不重叠区间数

return n - ans;

}

}

452.用最少数量的箭引爆气球

class Solution {

/**

* 题目:用最少数量的箭引爆气球

* 核心思路(贪心解法):

* 1. 贪心策略:优先选择「右边界最早」的气球,在其右边界射箭,尽可能引爆更多重叠气球

* 2. 问题本质:找"最多的不重叠区间数"(每个不重叠区间需要一支箭,与"无重叠区间"问题同源)

* 3. 排序规则:按气球右边界升序排序(核心!保证每次射箭位置是当前最靠左的有效位置)

* 时间复杂度:O(n log n)(排序 O(n log n) + 一次遍历 O(n))

* 空间复杂度:O(log n)(排序的系统栈空间)

*

* @param points 二维数组,每个元素为 [气球左边界, 气球右边界]

* @return 引爆所有气球所需的最少箭数量

*/

public int findMinArrowShots(int[][] points) {

// 边界条件:无气球时,无需射箭

if (points.length == 0) {

return 0;

}

// 步骤1:按气球「右边界」升序排序(贪心策略的核心前提)

// 注意:这里不用 point1[1] - point2[1] 直接相减,避免整数溢出(官方题解写法更安全)

// 排序后,前面的气球右边界更早,在其右边界射箭能覆盖更多后续重叠气球

Arrays.sort(points, new Comparator<int[]>() {

public int compare(int[] point1, int[] point2) {

if (point1[1] > point2[1]) {

return 1; // point1 右边界更大,排后面

} else if (point1[1] < point2[1]) {

return -1; // point1 右边界更小,排前面

} else {

return 0; // 右边界相等,顺序无关

}

}

});

// 步骤2:初始化贪心遍历的关键变量

int pos = points[0][1]; // 记录当前射箭的位置(初始为第一个气球的右边界)

int ans = 1; // 初始需要1支箭(至少引爆第一个气球)

// 步骤3:遍历剩余气球,判断是否需要新增箭

for (int[] balloon : points) {

// 关键判断:当前气球的左边界 > 上一次射箭位置 → 无重叠,需要新增箭

// 说明当前气球无法被上一支箭引爆,必须在其右边界重新射箭

if (balloon[0] > pos) {

pos = balloon[1]; // 更新射箭位置为当前气球的右边界

++ans; // 箭的数量+1

}

// 若当前气球左边界 ≤ 射箭位置 → 与当前箭的覆盖范围重叠,无需新增箭

}

return ans;

}

}

相关推荐
2401_841495641 小时前
【LeetCode刷题】轮转数组
数据结构·python·算法·leetcode·数组·双指针·轮转数组
Aspect of twilight2 小时前
LeetCode华为2025年秋招AI大模型岗刷题(四)
算法·leetcode·职场和发展
有泽改之_9 小时前
leetcode146、OrderedDict与lru_cache
python·leetcode·链表
im_AMBER9 小时前
Leetcode 74 K 和数对的最大数目
数据结构·笔记·学习·算法·leetcode
长安er10 小时前
LeetCode 206/92/25 链表翻转问题-“盒子-标签-纸条模型”
java·数据结构·算法·leetcode·链表·链表翻转
Benmao⁢10 小时前
C语言期末复习笔记
c语言·开发语言·笔记·leetcode·面试·蓝桥杯
CoderYanger11 小时前
动态规划算法-01背包问题:50.分割等和子集
java·算法·leetcode·动态规划·1024程序员节
菜鸟233号12 小时前
力扣513 找树左下角的值 java实现
java·数据结构·算法·leetcode
leoufung12 小时前
LeetCode 22:Generate Parentheses 题解(DFS / 回溯)
算法·leetcode·深度优先