目录
- [1. 一周中的第几天](#1. 一周中的第几天)
- [2. 公交站间的距离](#2. 公交站间的距离)
- [3. "气球" 的最大数量](#3. “气球” 的最大数量)
- [4. 最小绝对差](#4. 最小绝对差)
1. 一周中的第几天
给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天。
输入为三个整数:day、month 和 year,分别表示日、月、年。
您返回的结果必须是这几个值中的一个 {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}。
注意:1971 年 1 月 1 日是星期五。
示例 1:
输入:day = 31, month = 8, year = 2019
输出:"Saturday"
示例 2:
输入:day = 18, month = 7, year = 1999
输出:"Sunday"
示例 3:
输入:day = 15, month = 8, year = 1993
输出:"Sunday"
思路
本质是从1971年开始数,数到当前年份的前一年,其中要区分平年和闰年,然后当前年份又开始数,数到当前月份的前一个月份,注意月份是否大于2月且当前年份是平年还是闰年,最后加上天数,然后除以7天得到的余数就是星期几
java
class Solution {
private static final int[] Month = {0,31,28,31,30,31,30,31,31,30,31,30,31};
private static final String[] Week = {"Thursday","Friday", "Saturday","Sunday", "Monday", "Tuesday", "Wednesday"};
public String dayOfTheWeek(int day, int month, int year) {
int count = 0;
for(int i=1971;i<year;i++){
if(isLeapYear(i)){
count+=366;
}else{
count+=365;
}
}
for(int i=1;i<month;i++){
count += Month[i];
}
if(month>2&&isLeapYear(year)){
count++;
}
count+= day;
return Week[count%7];
}
private boolean isLeapYear(int year){
return year%400==0||(year%100!=0&&year%4==0);
}
}
时间复杂度: O(C),其中 C 为一年中的月份数 12。仅需常量时间的数学计算。
空间复杂度: O(C),其中 C 为一年中的月份数 12。仅需常量空间的数组。
2. 公交站间的距离
环形公交路线上有 n 个站,按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离,distance[i] 表示编号为 i 的车站和编号为 (i + 1) % n 的车站之间的距离。
环线上的公交车都可以按顺时针和逆时针的方向行驶。
返回乘客从出发点 start 到目的地 destination 之间的最短距离。
示例1:
输入:distance = [1,2,3,4], start = 0, destination = 1
输出:1
解释:公交站 0 和 1 之间的距离是 1 或 9,最小值是 1。
示例2:
输入:distance = [1,2,3,4], start = 0, destination = 2
输出:3
解释:公交站 0 和 2 之间的距离是 3 或 7,最小值是 3。
示例3:
输入:distance = [1,2,3,4], start = 0, destination = 3
输出:4
解释:公交站 0 和 3 之间的距离是 6 或 4,最小值是 4。
思路
一是理解distance[i]表示i到(i+1)%n站的距离,二是顺时针和逆时针和为环线总距离,因此只要计算顺时针和总距离即可
java
class Solution {
public int distanceBetweenBusStops(int[] distance, int start, int destination) {
int totalDis = 0;
int dis = 0;
int l = Math.min(start,destination),r=Math.max(start,destination);
for(int i=0;i<distance.length;i++){
totalDis += distance[i];
if(i>=l&&i<r){
dis+=distance[i];
}
}
return Math.min(totalDis-dis,dis);
}
}
时间复杂度: O(n),n表示数组长度
空间复杂度: O(1)
3. "气球" 的最大数量
给你一个字符串 text,你需要使用 text 中的字母来拼凑尽可能多的单词 "balloon"(气球)。
字符串 text 中的每个字母最多只能被使用一次。请你返回最多可以拼凑出多少个单词 "balloon"。
示例 1:
输入:text = "nlaebolko"
输出:1
示例 2:
输入:text = "loonbalxballpoon"
输出:2
示例3:
输入:text = "leetcode"
输出:0
思路
直接统计所有字母数量,再找出balon的数量的最小值,其中l和o需要除以2
java
class Solution {
public int maxNumberOfBalloons(String text) {
// 1. 初始化数组统计26个小写字母的频次
int[] count = new int[26];
for (char c : text.toCharArray()) {
count[c - 'a']++;
}
// 2. 提取 balloon 所需字符的频次
int b = count[1]; // 'b' - 'a' = 1
int a = count[0]; // 'a' - 'a' = 0
int l = count[11]; // 'l' - 'a' = 11
int o = count[14]; // 'o' - 'a' = 14
int n = count[13]; // 'n' - 'a' = 13
// 3. l和o各需要2个,所以除以2取整数
l /= 2;
o /= 2;
// 4. 最小值就是能拼凑的最大数量
return Math.min(Math.min(Math.min(b, a), l), Math.min(o, n));
}
}
4. 最小绝对差
给你个整数数组 arr,其中每个元素都 不相同。
请你找到所有具有最小绝对差的元素对,并且按升序的顺序返回。
每对元素对 [a,b] 如下:
a , b 均为数组 arr 中的元素
a < b
b - a 等于 arr 中任意两个元素的最小绝对差
示例 1:
输入:arr = [4,2,1,3]
输出:[[1,2],[2,3],[3,4]]
示例 2:
输入:arr = [1,3,6,10,15]
输出:[[1,3]]
示例 3:
输入:arr = [3,8,-10,23,19,-4,-14,27]
输出:[[-14,-10],[19,23],[23,27]]
思路
先排序再求相邻元素的差值即可,这里需要关注的是什么时候用什么方法解题,培养题感,知道什么时候用排序,什么时候不需要排序。本题中要找到最小绝对值的元素对,肯定要比较所有有序元素相邻两个的差值,然后取最小值,时间复杂度不可能小于排序时间复杂度,两两遍历的时间复杂度是O(n^2)
java
class Solution {
public List<List<Integer>> minimumAbsDifference(int[] arr) {
Arrays.sort(arr);
int minDis = Integer.MAX_VALUE;
List<List<Integer>> ans = new ArrayList<>();
for(int i=1;i<arr.length;i++){
int dis = arr[i]-arr[i-1];
if(dis<minDis){
ans.clear();
minDis = dis;
ans.add(Arrays.asList(arr[i-1],arr[i]));
}else if(dis==minDis){
ans.add(Arrays.asList(arr[i-1],arr[i]));
}
}
return ans;
}
}
时间复杂度: O(nlogn)
空间复杂度: O(n)