1603. 设计停车系统
请你给一个停车场设计一个停车系统。停车场总共有三种不同大小的车位:大,中和小,每种尺寸分别有固定数目的车位。
请你实现 ParkingSystem 类:
- ParkingSystem(int big, int medium, int small) 初始化 ParkingSystem 类,三个参数分别对应每种停车位的数目。
- bool addCar(int carType) 检查是否有 carType 对应的停车位。 carType 有三种类型:大,中,小,分别用数字 1, 2 和 3 表示。一辆车只能停在 carType 对应尺寸的停车位中。如果没有空车位,请返回 false ,否则将该车停入车位并返回 true 。
思路
这类题很简单,创建一个全局数组就行了
完整代码
public class ParkingSystem {
int[] parkingStation;
public ParkingSystem(int big, int medium, int small) {
parkingStation = new int[]{big ,medium, small};
}
public boolean addCar(int carType) {
if(parkingStation[carType - 1] != 0) {
parkingStation[carType - 1]--;
return true;
}
return false;
}
}
121. 买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
思路
因为只能先买入后面卖出。
所以维护最大值和最小值,当最小值更新的时候,之前的到的最大值也得更新。
完整代码
public int maxProfit(int[] prices) {
int n = prices.length;
int ans = 0;
int min = prices[0];
int max = prices[0];
for(int i = 0; i < n; i++){
if(prices[i] <= min){
min = prices[i];
max = prices[i];
}else{
max = prices[i];
ans = Math.max(max - min, ans);
}
}
return ans;
}
17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
思路
一开始只能想到暴力法求解。
对于这种 穷举类型的题目,需要用到的是回溯。回溯的题一般可以抽象为树形结构。
满足条件或者某个分支遍历完了之后就回撤。
回溯还是有点陌生,所以接下来几天都刷回溯的题
完整代码
private String[] map = {"abc", "def", "ghi", "jkl", "mno", "pqrs","tuv", "wxyz"};
private StringBuffer sb = new StringBuffer();
private List<String> ans = new ArrayList<>();
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() == 0) {
return ans;
}
backtrack(digits, 0);
return ans;
}
private void backtrack(String digits, int index) {
if(sb.length() == digits.length()) {
ans.add(sb.toString());
return;
}
String val = map[digits.charAt(index) - '2'];
for(char ch : val.toCharArray()) {
sb.append(ch);
backtrack(digits, index + 1);
sb.deleteCharAt(sb.length() - 1);
}
}
22. 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
思路
注意左边括号要严格大于右边
回溯的题大多有迹可循,要找到符合题目的条件才行
完整代码
List<String> ans = new ArrayList<>();
StringBuffer sb = new StringBuffer();
public List<String> generateParenthesis(int n) {
if(n == 0) {
return ans;
}
backTrack(n, n);
return ans;
}
public void backTrack(int left, int right) {
if(left == 0 && right == 0) {
ans.add(sb.toString());
return;
}
if(left > right) {//左边括号要严格大于右边,不符合条件,跳过
return;
}
if(left > 0) {
sb.append("(");
backTrack(left - 1, right);
sb.deleteCharAt(sb.length() - 1);//回撤
}
if(right > 0) {
sb.append(")");
backTrack(left, right - 1);
sb.deleteCharAt(sb.length() - 1);
}
}
1688. 比赛中的配对次数
给你一个整数 n ,表示比赛中的队伍数。比赛遵循一种独特的赛制:
如果当前队伍数是 偶数 ,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。
如果当前队伍数为 奇数 ,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。
返回在比赛中进行的配对次数,直到决出获胜队伍为止。
思路
这道题比较简单。虽然归类在回溯,而不是回溯。。。
完整代码
int ans = 0;
public int numberOfMatches(int n) {
if(n == 1){
return ans;
}
backTrack(n);
return ans;
}
public void backTrack(int nums){
if(nums == 0 || nums == 1){
ans += 0;
return;
}
if(nums % 2 == 0){
ans += nums / 2;
backTrack(nums / 2);
}
if(nums % 2 != 0){
ans += (nums - 1) / 2;
backTrack((nums - 1) / 2 + 1);
}
}