难度 中等
这里有
n
个航班,它们分别从1
到n
进行编号。有一份航班预订表
bookings
,表中第i
条预订记录bookings[i] = [firsti, lasti, seatsi]
意味着在从firsti
到lasti
(包含firsti
和lasti
)的 每个航班 上预订了seatsi
个座位。请你返回一个长度为
n
的数组answer
,其中answer[i]
是航班i
上预订的座位总数。示例 1:
输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5 输出:[10,55,45,25,25] 解释: 航班编号 1 2 3 4 5 预订记录 1 : 10 10 预订记录 2 : 20 20 预订记录 3 : 25 25 25 25 总座位数: 10 55 45 25 25 因此,answer = [10,55,45,25,25]示例 2:
输入:bookings = [[1,2,10],[2,2,15]], n = 2 输出:[10,25] 解释: 航班编号 1 2 预订记录 1 : 10 10 预订记录 2 : 15 总座位数: 10 25 因此,answer = [10,25]
暴力题解
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int []res=new int[n];
for (int i = 0; i <bookings.length ; i++) {
for(int j=bookings[i][0];j<=bookings[i][1];j++){
res[j-1]=res[j-1]+bookings[i][2];
}
}
return res;
}
}
2官方题解:差分法
可以看看大佬对差分法的解释:
换一种思路理解题意,将问题转换为:某公交车共有 n 站,第 i 条记录 bookings[i] = [i, j, k] 表示在 i 站上车 k 人,乘坐到 j 站,在 j+1 站下车,需要按照车站顺序返回每一站车上的人数
根据 1 的思路,定义 counter[] 数组记录每站的人数变化,counter[i] 表示第 i+1 站。遍历 bookings[]:bookings[i] = [i, j, k] 表示在 i 站增加 k 人即 counters[i-1] += k,在 j+1 站减少 k 人即 counters[j] -= k
遍历(整理)counter[] 数组,得到每站总人数: 每站的人数为前一站人数加上当前人数变化 counters[i] += counters[i - 1]
public class CorporateFlightBookings {
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] counters = new int[n];
for (int[] booking : bookings) {
counters[booking[0] - 1] += booking[2];
if (booking[1] < n) {
//根据题意如果不是完全做到头的话,比如做到第k站,就会在k+1站下车。每次循环先把数组索引为下车站出的
// 值减去booking[2]
counters[booking[1]] -= booking[2];
}
}
//前缀和,这一站的人为没下车的人+本站上车的人
for (int i = 1; i < n; ++i) {
counters[i] += counters[i - 1];
}
return counters;
}
}
难度简单137收藏分享切换为英文接收动态反馈
给定一个单词,你需要判断单词的大写使用是否正确。
我们定义,在以下情况时,单词的大写用法是正确的:
- 全部字母都是大写,比如"USA"。
- 单词中所有字母都不是大写,比如"leetcode"。
- 如果单词不只含有一个字母,只有首字母大写, 比如 "Google"。
否则,我们定义这个单词没有正确使用大写字母。
示例 1:
输入: "USA" 输出: True示例 2:
输入: "FlaG" 输出: False
两种笨方法
class Solution {
public boolean detectCapitalUse(String word) {
int len=word.length();
int big=0,small=0;
for(int i=0;i<len;i++){
if(word.charAt(i)-'a'>=0){
small++;
}else{
big++;
}
}
return big==len||big==0||word.charAt(0)-'a'<0 && big==1;
}
}
class Solution {
public boolean detectCapitalUse(String word) {
int len=word.length();
int big=0,small=0;
for(int i=0;i<len;i++){
if(((int)word.charAt(i))>=65 && ((int)word.charAt(i))<=90){
big++;
}
}
return big==len||big==0||((int)word.charAt(0))>=65 && ((int)word.charAt(0))<=90 &&big==1;
}
}
难度中等329收藏分享切换为英文接收动态反馈
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
示例 1:
输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。 因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。示例 2:
输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。 注意"cacaca"是不正确的,因为相同的字母必须放在一起。示例 3:
输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。 注意'A'和'a'被认为是两种不同的字符。
学会使用StringBuffer和StringBuilder解决问题,因为String使用不方便,一旦定义好就是固定的,不会被改变,给字符串重新赋值并不是改变,而是变量指向改变了。
class Solution {
public String frequencySort(String s) {
HashMap<Character,Integer> map=new HashMap<>();
//统计出现的频率
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
int x=map.getOrDefault(c,0)+1;
map.put(c,x);
}
StringBuilder res=new StringBuilder();
Map<Character,Integer> tmp=new HashMap(map);
for(int i=0;i<s.length();i++){
for(char c:tmp.keySet()){
//对频率-1,为0的话,就插入原频率个该字符
tmp.put(c,tmp.get(c)-1);
if(tmp.get(c)==0){
for(int j=0;j<map.get(c);j++){
res.append(c);
}
}
}
}
//对结果进行反转,得到正确结果。
return res.reverse().toString();
}
}
难度简单126收藏分享切换为英文接收动态反馈
给你一个正整数数组
arr
,请你计算所有可能的奇数长度子数组的和。子数组 定义为原数组中的一个连续子序列。
请你返回
arr
中 所有奇数长度子数组的和 。示例 1:
输入:arr = [1,4,2,5,3] 输出:58 解释:所有奇数长度子数组和它们的和为: [1] = 1 [4] = 4 [2] = 2 [5] = 5 [3] = 3 [1,4,2] = 7 [4,2,5] = 11 [2,5,3] = 10 [1,4,2,5,3] = 15 我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58 示例 2:输入:arr = [1,2] 输出:3 解释:总共只有 2 个长度为奇数的子数组,[1] 和 [2]。它们的和为 3 。 示例 3:输入:arr = [10,11,12] 输出:66
class Solution {
public int sumOddLengthSubarrays(int[] arr) {
int len=arr.length;
int sum=0;
for(int i=1;i<=len;i+=2){
for(int k=0;k<len-i+1;k++){
for(int x=0;x<i;x++){
sum+=arr[x+k];
}
}
}
return sum;
}
}
难度简单129收藏分享切换为英文接收动态反馈
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例:
s = "abaccdeff" 返回 "b" s = "" 返回 " "
class Solution {
public char firstUniqChar(String s) {
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(s.indexOf(c)==i && s.indexOf(c,i+1)==-1){
return c;
}
}
return ' ';
}
}
难度简单4收藏分享切换为英文接收动态反馈
给你一个整数数组
nums
,请计算数组的 中心下标 。数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为
0
,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回
-1
。示例 1:
输入:nums = [1,7,3,6,5,6] 输出:3 解释: 中心下标是 3 。 左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 , 右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。示例 2:
输入:nums = [1, 2, 3] 输出:-1 解释: 数组中不存在满足此条件的中心下标。示例 3:
输入:nums = [2, 1, -1] 输出:0 解释: 中心下标是 0 。 左侧数之和 sum = 0 ,(下标 0 左侧不存在元素), 右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。
思路:如果i是结果,i前数组元素和x,则x*2+nums[i]=sum
class Solution {
public int pivotIndex(int[] nums) {
int sum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
}
int x=0;
for(int i=0;i<nums.length;i++){
if(i==0){
x=0;
}else{
x+=nums[i-1];
}
if(x*2+nums[i]==sum){
return i;
}
}
return -1;
}
}
难度简单430收藏分享切换为英文接收动态反馈
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
示例 1:
输入: n = 5, m = 3 输出: 3示例 2:
输入: n = 10, m = 17 输出: 2
class Solution {
public int lastRemaining(int n, int m) {
ArrayList<Integer> list=new ArrayList<>(n);
for(int i=0;i<n;i++){
list.add(i);
}
int index=0;
while(list.size()!=1){
index=(m-1+index)%list.size();
list.remove(index);
}
return list.get(0);
}
}