This commit is contained in:
toly
2023-11-08 09:35:29 +08:00
parent 88cd6fb3b4
commit 8fb4bf57d6
78 changed files with 4344 additions and 544 deletions

View File

@@ -1,4 +1,4 @@
///
///
//
//

104
test/algorithm/1052.dart Normal file
View File

@@ -0,0 +1,104 @@
/// 1052. 爱生气的书店老板
//有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。
// 给定一个长度为 n 的整数数组 customers
// 其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。
// 在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1
// 否则 grumpy[i] = 0。 当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。
// 书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。
// 请你返回 这一天营业下来,最多有多少客户能够感到满意 。
//
//输入customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], minutes = 3
// 输出16
// 解释:书店老板在最后 3 分钟保持冷静。
// 感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.
//
// 算法思想:
// 因为有X分钟可以控制情绪所以这X分钟要用在关键的时间段也就是需要知道哪个长度为X的时间段不满意的客人最多。
// 最多满意客户数量 = 原本就满意的客户 + X时间段内因为控制了情绪而态度反转的最多客户数量
//
// 算法步骤:
//
// 统计老板不生气时的客人数量;
// 利用长度为X的滑动窗口统计长度为X的时间段内不满意的客户最多数量是多少
import 'dart:math';
void main() {
List<int> customers = [4, 6, 3, 8, 7, 2, 6];
//1生气 0不气
List<int> grumpy = [1, 0, 1, 1, 0, 1, 0];
//最大不满数 3+8
// 没有魔法时满意数 6+7+6 = 19
//拥有魔法 6+3+8+7+6 =30
int magic = 2;
maxSatisfied(customers, grumpy, magic);
}
// int maxSatisfied(List<int> customers, List<int> grumpy, int minutes) {
// int m = customers.length;
// int total = 0;
// // 统计不生气时间内的客人总数
// for (int i = 0; i < m; i++) {
// if (grumpy[i] == 0) {
// total += customers[i];
// }
// }
// int curAngry = 0; // 长度为X的时间段内不满意的客人数
// // 统计第一个大小为X的窗口内不满意的客人数
// for (int i = 0; i < minutes; i++) {
// curAngry += customers[i] * grumpy[i];
// }
// int maxAngry = curAngry; // 所有窗口时间段内,遇到不满意的客人的最多数量
// // 滑动窗口统计max_angry
// for (int i = minutes; i < m; i++) {
// curAngry += customers[i] * grumpy[i]; // 只把不满意的客人数量加进来
// curAngry -= customers[i - minutes] * grumpy[i - minutes]; // 只减去不满意客人数量
// maxAngry = max(maxAngry, curAngry); // 更新窗口内的不满意客人数量
// }
// // 总满意人数 = 本来就满意的人数 + 老板抑制情绪的时间段内不满意变为满意的人数
// return total + maxAngry;
// }
///最大满意人数
int maxSatisfied(List<int> customers, List<int> grumpy, int minutes) {
int maxSatisNumber = 0;
int maxUnSatisNumber = 0;
int unSatisNumber = 0;
//先算第一个窗口不满意人数
for (int i = 0; i < minutes; i++) {
if (grumpy[i] == 1) {
maxUnSatisNumber += customers[i];
unSatisNumber = maxUnSatisNumber;
}
}
//格口向后移动
for (int i = minutes; i < customers.length; i++) {
//减去前一个格口不满数 加上后一个格口不满数
if (grumpy[i - minutes] == 1) {
if (grumpy[i] == 1) {
unSatisNumber = unSatisNumber - customers[i - minutes] + customers[i];
} else {
unSatisNumber = unSatisNumber - customers[i - minutes] + 0;
}
} else {
if (grumpy[i] == 1) {
unSatisNumber = unSatisNumber - 0 + customers[i];
} else {
unSatisNumber = unSatisNumber - 0 + 0;
}
}
maxUnSatisNumber = max(maxUnSatisNumber, unSatisNumber);
}
print("最大不满意数$maxUnSatisNumber");
for (int i = 0; i < customers.length; i++) {
if (grumpy[i] == 0) {
maxSatisNumber += customers[i];
}
}
maxSatisNumber = maxSatisNumber + maxUnSatisNumber;
print("最大满意数$maxSatisNumber");
return maxSatisNumber;
}

View File

@@ -0,0 +1,85 @@
import 'dart:math';
/// 子数组最大平均数
///
///给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。
/// 请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。
///输入nums = [1,12,-5,-6,50,3], k = 4
///输出12.75
///解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
///滑动窗口解法
//class Solution:
// def problemName(self, s: str) -> int:
// # Step 1: 定义需要维护的变量们 (对于滑动窗口类题目,这些变量通常是最小长度,最大长度,或者哈希表)
// x, y = ..., ...
//
// # Step 2: 定义窗口的首尾端 (start, end) 然后滑动窗口
// start = 0
// for end in range(len(s)):
// # Step 3: 更新需要维护的变量, 有的变量需要一个if语句来维护 (比如最大最小长度)
// x = new_x
// if condition:
// y = new_y
//
// '''
// ------------- 下面是两种情况读者请根据题意二选1 -------------
// '''
// # Step 4 - 情况1
// # 如果题目的窗口长度固定用一个if语句判断一下当前窗口长度是否达到了限定长度
// # 如果达到了,窗口左指针前移一个单位,从而保证下一次右指针右移时,窗口长度保持不变,
// # 左指针移动之前, 先更新Step 1定义的(部分或所有)维护变量
// if 窗口长度达到了限定长度:
// # 更新 (部分或所有) 维护变量
// # 窗口左指针前移一个单位保证下一次右指针右移时窗口长度保持不变
//
// # Step 4 - 情况2
// # 如果题目的窗口长度可变: 这个时候一般涉及到窗口是否合法的问题
// # 如果当前窗口不合法时, 用一个while去不断移动窗口左指针, 从而剔除非法元素直到窗口再次合法
// # 在左指针移动之前更新Step 1定义的(部分或所有)维护变量
// while 不合法:
// # 更新 (部分或所有) 维护变量
// # 不断移动窗口左指针直到窗口再次合法
//
// # Step 5: 返回答案
// return ...
//
void main() {
List<int> num = [4, 6, 3, 8, 7, 2, 6];
print("${findMaxAverage(num, 3)}");
}
//
double findMaxAverage(List<int> num, int k) {
int sum = 0;
int n = num.length;
//窗口大小
for (int i = 0; i < k; i++) {
sum += num[i];
}
int maxSum = sum;
for (int i = k; i < n; i++) {
sum = sum - num[i - k] + num[i];//减前一个 + 后一个 == 相当于视口向前滑动一格
//第一次 sum = num[0]+num[1] - num[0] + num[2] = num[1] + num[2]
//第二次 sum = num[1]+num[2] - num[1] +num[3] = num[2] + num[3]
maxSum = max(maxSum, sum);
}
return 1.0 * maxSum / k;
}
// double findMaxAverage(List<int> num, int k) {
// int maxSum = 0;
// //窗口开始的和
// for (int i = 0; i < k; i++) {
// maxSum += num[i];
// }
// for( int i = k;i<num.length;i++){
//
//
// }
//
//
//
// return maxSum / k;
// }