求会议房间数量
题目
大概意思是说输入几个会议的开始时间和结束时间,判断最少需要几个会议室。
思路
这题用快慢指针,之前做过类似的题。但是一直在调输入输出,写的心好累。下面的代码我用二维数组代替一下输入,我恨,看来在线OJ还是有必要练一下。
代码
public int minMeetingRooms(int[][] intervals) {
if (intervals == null || intervals.length == 0) {
return 0;
}
// 创建两个数组,分别保存会议的开始时间和结束时间
int[] startTimes = new int[intervals.length];
int[] endTimes = new int[intervals.length];
// 填充开始时间和结束时间数组
for (int i = 0; i < intervals.length; i++) {
startTimes[i] = intervals[i][0];
endTimes[i] = intervals[i][1];
}
// 对开始时间和结束时间进行排序
Arrays.sort(startTimes);
Arrays.sort(endTimes);
int startPointer = 0, endPointer = 0;
int rooms = 0, maxRooms = 0;
// 使用两个指针分别扫描开始和结束时间
while (startPointer < intervals.length) {
if (startTimes[startPointer] < endTimes[endPointer]) {
// 如果有会议开始但还没有结束,则需要新的会议室
rooms++;
startPointer++;
} else {
// 否则,结束一个会议,释放一个会议室
rooms--;
endPointer++;
}
// 更新最大房间数
maxRooms = Math.max(maxRooms, rooms);
}
return maxRooms;
}
求最长的无重复元素子数组
题目
就是求最长的无重复元素子数组
思路
博主肯定是昨天做动态规划魔怔了,一直在找状态转移方程,样例过了,总共A了百分之二十几。最后才想起要用滑动窗口,心碎了💔
代码
public int lengthOfLongestSubstring(int[] nums) {
Set<Integer> set = new HashSet<>(); // 用于存储窗口中的元素
int left = 0; // 滑动窗口左边界
int maxLength = 0; // 最长的无重复子数组长度
for (int right = 0; right < nums.length; right++) {
// 如果遇到重复元素,缩小窗口
while (set.contains(nums[right])) {
set.remove(nums[left]);
left++;
}
// 将当前元素添加到集合中
set.add(nums[right]);
// 更新最大长度
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
求覆盖子串的最小长度
题目
即给定一个字符串s和t,找出s中包含t中所有字符的最小长度
思路
做过类似的题目,前几天才做的,八分钟直接A了。
代码
public String minWindow(String S, String t) {
char[] s = S.toCharArray();
int m = s.length;
int ansLeft = -1;
int ansRight = m;
int left = 0;
int[] cntS = new int[128];
int[] cntT = new int[128];
for (char c : t.toCharArray()) {
cntT[c]++;
}
for (int right = 0; right < m; right++) {
cntS[s[right]]++;
while (isCovered(cntS, cntT)) {
if (right - left < ansRight - ansLeft) {
ansLeft = left;
ansRight = right;
}
cntS[s[left++]]--; // 左端点字母移出子串
}
}
return ansLeft < 0 ? "" : S.substring(ansLeft, ansRight + 1);
}
private boolean isCovered(int[] cntS, int[] cntT) {
for (int i = 'A'; i <= 'Z'; i++) {
if (cntS[i] < cntT[i]) {
return false;
}
}
for (int i = 'a'; i <= 'z'; i++) {
if (cntS[i] < cntT[i]) {
return false;
}
}
return true;
}
求最短路径长度
题目
给定k,m,n,k代表体力,要从(0,0)走到(m,n)。请问是否能走到,如果可以给出最短路径的数量,不可以则输出0
思路
我直接BFS,结果A了50%,时间超限了。仔细一琢磨,要走出最短路径,那么只能往下或者往左走,一共走m+n步,感觉这是个数学问题。最后也没想出来,败在这里了。
chat了一下好像说我的做法没错,但是可以剪枝。我看了一下他提供的代码,时间复杂度和我的差不多。
// 定义四个方向:上、下、左、右
private static final int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public int minPathCount(int m, int n, int k) {
// 边界条件判断
if (k < m + n) {
return 0; // 如果体力不足以走到终点,直接返回 0
}
// 队列存储当前坐标及剩余体力
Queue<int[]> queue = new LinkedList<>();
// 记录每个点的最短路径数,初始值为 0
int[][] pathCount = new int[m + 1][n + 1];
// 用于记录每个点是否访问过,及体力消耗
boolean[][] visited = new boolean[m + 1][n + 1];
// 起点 (0, 0),初始体力为 k,路径数量为 1
queue.offer(new int[]{0, 0, k});
pathCount[0][0] = 1;
visited[0][0] = true;
// 记录步数
int steps = 0;
// 开始 BFS
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] current = queue.poll();
int x = current[0];
int y = current[1];
int remainingK = current[2];
// 如果到达终点 (m, n),返回最短路径数量
if (x == m && y == n) {
return pathCount[m][n];
}
// 遍历四个方向
for (int[] direction : directions) {
int newX = x + direction[0];
int newY = y + direction[1];
// 确保新位置在范围内,体力充足,且未访问过
if (newX >= 0 && newX <= m && newY >= 0 && newY <= n && remainingK > 0) {
// 如果该位置未访问过,或体力更充足时可以再次访问
if (!visited[newX][newY] || remainingK - 1 > 0) {
queue.offer(new int[]{newX, newY, remainingK - 1});
visited[newX][newY] = true;
// 增加路径数量
pathCount[newX][newY] += pathCount[x][y];
}
}
}
}
steps++; // 步数增加
}
// 无法到达终点,返回 0
return 0;
}