代码随想录第二十九天| 134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列

markdown
复制代码

134. 加油站

题目描述

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1


解题思路

  1. 计算每站的盈亏值

    • 计算每个加油站的盈亏值 dis[i] = gas[i] - cost[i],表示从加油站 i 出发后的净剩油量。
    • 如果总盈亏和 sum 小于 0,则不可能绕环路行驶一周,直接返回 -1
  2. 寻找起点

    • 用变量 leftsum 记录当前路径的累计盈亏和。
    • 如果某一站的 leftsum < 0,说明从当前站出发无法走到下一站,则将下一站作为新的起点,重置 leftsum = 0
  3. 最终判断

    • 如果 sum >= 0,说明可以完成环路,返回起点编号 left
    • 如果 sum < 0,说明无论从哪一站出发都无法完成环路,返回 -1

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int[] dis = new int[gas.length];
		int flag = 0;
		int sum = 0;
		int left = 0;
		int leftsum = 0;
		for(int i=0;i<gas.length;i++){
			dis[i] = gas[i] - cost[i];
			sum = sum + dis[i];
			leftsum = leftsum + dis[i];
			if(leftsum < 0){
				left = i + 1;
				leftsum = 0;
			}
		}
		if(sum<0){
			return -1;
		}else {
			return left;
		}
    }
}

markdown
复制代码

135. 分发糖果

题目描述

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

  1. 每个孩子至少分配到 1 个糖果。
  2. 相邻的孩子中,评分高的孩子必须获得更多的糖果。

计算老师至少需要准备多少颗糖果。


解题思路

  1. 两次遍历解决问题

    • 从左到右遍历:
      • 如果当前孩子的评分比前一个孩子高,则当前孩子的糖果数比前一个孩子多 1。
    • 从右到左遍历:
      • 如果当前孩子的评分比后一个孩子高,且当前糖果数不超过后一个孩子,则更新当前孩子的糖果数为后一个孩子的糖果数 + 1。
  2. 计算总糖果数

    • 在两次遍历的过程中累加糖果数。
  3. 时间复杂度

    • 两次遍历数组,时间复杂度为 O(n),空间复杂度为 O(n)。

Java代码

class Solution {
    public int candy(int[] ratings) {
        int count = ratings.length;
		int[] nums = new int[ratings.length];
		nums[0] = 0;
		for(int i = 0;i< ratings.length-1;i++){
			if(ratings[i]<ratings[i+1]){
				nums[i+1] = nums[i] + 1;
			}
		}
		for(int i = ratings.length-1;i>0;i--){
			if(ratings[i-1]>ratings[i] && nums[i-1] <= nums[i]){
				nums[i-1] = nums[i] + 1;
			}
			count = count + nums[i];
		}
		return count + nums[0];

    }
}

860. 柠檬水找零

题目描述

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。

顾客排队购买你的产品(按账单 bills 支付的顺序)一次购买一杯。

  • 每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。
  • 你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意:

  • 一开始你手头没有任何零钱。

如果你能给每位顾客正确找零,返回 true,否则返回 false


解题思路

  1. 维护零钱数量

    • 使用数组 money 记录手中的零钱:
      • money[0] 表示 5 美元的数量。
      • money[1] 表示 10 美元的数量。
      • money[2] 表示 20 美元的数量。
  2. 逐步处理顾客支付

    • 如果顾客支付 5 美元:
      • 不需要找零,直接增加 money[0]
    • 如果顾客支付 10 美元:
      • 找零需要 5 美元,减少 money[0]
      • 如果 money[0] < 0,返回 false
    • 如果顾客支付 20 美元:
      • 优先用 10 美元和 5 美元找零(减少 money[1]money[0])。
      • 如果没有 10 美元,则使用 3 张 5 美元找零。
      • 如果零钱不足,返回 false
  3. 时间复杂度

    • 每个顾客支付处理的操作是 O(1),总时间复杂度为 O(n),空间复杂度为 O(1)。

Java代码

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int[] money = new int[3];
		
		for(int i = 0;i< bills.length;i++){
			if(bills[i]==5){
				money[0] = money[0] + 1;
			} else if (bills[i]==10) {
				money[1] = money[1] + 1;
				money[0] = money[0] - 1;
				if(money[0]<0){
					return false;
				}
			}else if (bills[i]==20) {
				money[2] = money[2] + 1;
				if(money[1]>0 && money[0]>0){
					money[1] = money[1] - 1;
					money[0] = money[0] - 1;
				} else if (money[0]>=3) {
					money[0] = money[0] - 3;
				}else {
					return false;
				}
			}

		}
		return true;
    }
}

406. 根据身高重建队列

题目描述

假设有一群打乱顺序的人站成一个队列,数组 people 表示队列中一些人的属性。
每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi,前面正好有 ki 个身高大于或等于 hi 的人。

请重新构造并返回输入数组 people 所表示的队列。
返回的队列应该格式化为数组 queue,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性。


解题思路

  1. 排序

    • 首先按身高 hi 降序排列(即高个子优先),如果身高相同,则按 ki 升序排列。
    • 排序后,高个子优先占位,低个子只能插入到指定位置,保证不影响已插入的高个子。
  2. 插入

    • 使用链表模拟插入操作。
    • 按排序结果依次将每个人插入到链表中指定的位置 ki
  3. 时间复杂度

    • 排序的时间复杂度为 O(n log n),插入的复杂度为 O(n^2)(因为链表插入需要 O(n) 时间)。
    • 总时间复杂度为 O(n^2)。

Java代码

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people,(a,b)->{
			if(a[0] == b[0]) return a[1] - b[1];
			return b[0] - a[0];
		});
		LinkedList<int[]> que = new LinkedList<>();

		for(int[] p :people){
			que.add(p[1],p);
		}

		return que.toArray(new int[people.length][]);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值