链接:https://leetcode.com/tag/heap/

【23】 Merge k Sorted Lists

【215】 Kth Largest Element in an Array (无序数组中最小/大的K个数)(2018年11月30日第一次复习)

给了一个无序数组,可能有重复数字,找到第 k 个最大的元素并且返回这个元素值。

题解:直接用直接用个堆保存数组中最大的 K 个数。时间复杂度是 O(NlogK)。

 //时间复杂度是 O(NlogK), 用堆辅助。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
const int n = nums.size();
priority_queue<int, vector<int>, greater<int>> pq;
for (int i = ; i < n; ++i) {
if (pq.size() < k) {
pq.push(nums[i]);
} else {
if (pq.top() < nums[i]) {
pq.pop();
pq.push(nums[i]);
}
}
}
return pq.top();
}
};

本题可以有 O(N) 的解法,详见《剑指offer》或者《程序员代码面试指南》P336

做法是quickSelect。

【218】 The Skyline Problem(2019年2月5日,算法群打卡复习)

给了一个tuple list, 每个三元组 [a, b, h] 代表一个楼的x轴坐标是在[a, b],楼的高度是 h,返回所有楼轮廓的左上角坐标。

题解:用了一个 multiset 来存这个楼是进来还是出去,如果是进来,就存[a, h], 如果是出去,就存[b, -h]。 然后遍历这个 multiset,如果这个楼是进来的话,就看当前高度它是不是最高的,如果是,那么这个点在答案中,如果这个楼是出去的话,先把这个高度删除,然后看当前这个高度是不是比剩下所有楼都高,如果是,就把当前坐标和剩下的最高的楼组成的坐标加入答案中。

 class Solution {
public:
vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
for (auto& b : buildings) {
record.insert(make_pair(b[], b[]));
record.insert(make_pair(b[], -b[]));
}
vector<pair<int, int>> ret;
for (auto& r : record) {
bool entry = r.second > ? true : false;
int idx = r.first, h = abs(r.second);
// printf("idx = %d, h = %d, entry = %d\n", idx, h, entry);
if (entry) {
if (h > getMaxHeight()) {
ret.push_back(make_pair(idx, h));
}
height.insert(h);
} else {
auto iter = height.find(h);
height.erase(iter);
if (h > getMaxHeight()) {
ret.push_back(make_pair(idx, getMaxHeight()));
}
}
}
return ret;
}
struct kcmp {
bool operator() (const pair<int, int>& p1, const pair<int, int>& p2) const {
if (p1.first == p2.first) {
return p1.second > p2.second;
}
return p1.first < p2.first;
}
};
multiset<pair<int, int>, kcmp> record;
multiset<int> height;
int getMaxHeight() {
if (height.empty()) {return ;}
return *height.rbegin();
}
};

【239】 Sliding Window Maximum (2019年2月18日复习)(用deque做)

求一个滑动窗口的最大值。

题解:用deque做。单调队列。一开始还想错了,需要多跑几个case验证一下正确性。时间复杂度是O(N)

 class Solution {
public:
// [1 3 -1] -3 5 3 6 7
// 0 1 2
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
const int n = nums.size();
deque<int> dq;
vector<int> res;
for (int i = ; i < n; ++i) {
if (!dq.empty() && i - dq.front() >= k) {
dq.pop_front();
}
while (!dq.empty() && nums[dq.back()] < nums[i]) {
dq.pop_back();
}
dq.push_back(i);
if (i - k + >= ) {
res.push_back(nums[dq.front()]);
}
}
return res;
}
};

【253】 Meeting Rooms II

题意是252的升级版,给了一个数组,数组里面的每个元素代表一个会议的开始时间和结束时间,问想安排下所有的会议,至少需要多少个会议室。

题解:这个题目在 sort 的分类里面说过,链接:https://www.cnblogs.com/zhangwanying/p/9914941.html

【264】 Ugly Number II

返回第 N 个丑数,丑数的定义是因子只有2 ,3 ,5 的数。

题解:我们用三根指针指向ans中应该乘2, 3 ,5的位置,然后从中选出最小的元素。

 class Solution {
public:
int nthUglyNumber(int n) {
vector<int> nums(n, INT_MAX);
nums[] = ;
int p1 = , p2 = , p3 = ;
for (int i = ; i < n; ++i) {
int minn = min(nums[p1] * , min(nums[p2] * , nums[p3] * ));
if (minn == nums[p1] * ) {++p1;}
if (minn == nums[p2] * ) {++p2;}
if (minn == nums[p3] * ) {++p3;}
nums[i] = minn;
}
return nums[n-];
}
};

【295】 Find Median from Data Stream (2018年11月30日,堆的题目)

给了一个数据流,设计api接口,addNum() 用于接收一个数,findMedian() 用于返回数据流的中位数。返回数据流的中位数。

Example:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

题解:这题是今天看算法课看到的一个题,我们用一个大根堆存储数据流比较小的一半数字,用一个小根堆存数据流的比较大的一半数字。(这两个堆的元素个数要么相等,要么存小数的那个堆比存大数的那个堆多存一个数。)中位数如果两个堆元素个数相差 1 ,那么就返回大根堆的堆顶。不然返回两个堆顶的平均数。

 class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() { }
void addNum(int num) {
lowhalf.push(num);
int k = lowhalf.top(); lowhalf.pop();
highhalf.push(k);
if (lowhalf.size() < highhalf.size()) {
k = highhalf.top(); highhalf.pop();
lowhalf.push(k);
}
return;
}
double findMedian() {
if (lowhalf.size() == highhalf.size()) {
return (double)(lowhalf.top() + highhalf.top()) / ;
}
return (double)lowhalf.top();
}
priority_queue<int, vector<int>, greater<int>> lowhalf; //小根堆存大的那边
priority_queue<int> highhalf; //大根堆存小的那边
}; /**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/

【313】 Super Ugly Number (2019年2月9日,heap复习)

给了一个prime的数组(数组中 m 个元素),返回第 n 个 ugly number,ugly number 的定义是所有的因子都必须是 prime 数组中的元素。

题解:解法同因子是 2,3,5 的丑数,我们用 m 个指针分别指向prime数组中数应该乘的位置。然后同ugly number那题一样。时间复杂度是 O(N*M)

 class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
const int m = primes.size();
sort(primes.begin(), primes.end());
vector<int> ptr(m, );
vector<int> ans(n, INT_MAX);
ans[] = ;
for (int i = ; i < n; ++i) {
int minn = INT_MAX;
for (int k = ; k < m; ++k) {
minn = min(minn, ans[ptr[k]] * primes[k]);
}
for (int k = ; k < m; ++k) {
if (minn == ans[ptr[k]] * primes[k]) {
ptr[k]++;
}
}
ans[i] = minn;
}
return ans[n-];
}
};

【347】 Top K Frequent Elements

【355】 Design Twitter (2018年12月3日,heap专题)

实现四个 api。

  1. postTweet(userId, tweetId): Compose a new tweet.
  2. getNewsFeed(userId): Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.
  3. follow(followerId, followeeId): Follower follows a followee.
  4. unfollow(followerId, followeeId): Follower unfollows a followee.
Example:
Twitter twitter = new Twitter(); // User 1 posts a new tweet (id = 5).
twitter.postTweet(1, 5); // User 1's news feed should return a list with 1 tweet id -> [5].
twitter.getNewsFeed(1); // User 1 follows user 2.
twitter.follow(1, 2); // User 2 posts a new tweet (id = 6).
twitter.postTweet(2, 6); // User 1's news feed should return a list with 2 tweet ids -> [6, 5].
// Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5.
twitter.getNewsFeed(1); // User 1 unfollows user 2.
twitter.unfollow(1, 2); // User 1's news feed should return a list with 1 tweet id -> [5],
// since user 1 is no longer following user 2.
twitter.getNewsFeed(1);

题解:用个 unordered_map 标记用户关系,然后一个 vector 存储 twitter post

 class Twitter {
public:
/** Initialize your data structure here. */
Twitter() { } /** Compose a new tweet. */
void postTweet(int userId, int tweetId) {
twit.push_back(make_pair(userId, tweetId));
} /** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId) {
set<int> people = followRelation[userId];
people.insert(userId);
vector<int> ret;
int idx = twit.size() - , cnt = ;;
while (cnt < && idx >= ) {
auto p = twit[idx--];
int uid = p.first, tid = p.second;
if (people.find(uid) != people.end()) {
ret.push_back(tid);
cnt++;
}
}
return ret;
} /** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId) {
followRelation[followerId].insert(followeeId);
} /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId) {
if (followRelation.find(followerId) == followRelation.end()) { return; }
if (followRelation[followerId].find(followeeId) == followRelation[followerId].end()) {return;}
followRelation[followerId].erase(followeeId);
} unordered_map<int, set<int>> followRelation;
vector<pair<int, int>> twit; // (user, id)
}; /**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* vector<int> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/

【358】 Rearrange String k Distance Apart

【373】 Find K Pairs with Smallest Sums (2018年12月1日)

给了两个整数数组 nums1 和 nums2, 和一个整数 k,求 nums1 和 nums2 的笛卡尔积中(就是 nums1 中选择一个数字 n1,nums2 中选择一个数字 n2 组成pair),sum 最小的 k 个pair。

题解:本题就是自定义排序的大根堆,pair排序的规则是 sum 大的在堆顶。

 class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
if (nums1.empty() || nums2.empty()) {return vector<pair<int, int>>();}
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> pq;
for (auto n1 : nums1) {
for (auto n2 : nums2) {
pq.push(make_pair(n1, n2));
if (pq.size() > k) { pq.pop(); }
}
}
vector<pair<int, int>> ret; //可能nums1和nums2的组合的pair不够 k 个,所以不能一开始初始化为 k 个结果。
while (!pq.empty()) {
ret.push_back(pq.top());
pq.pop();
}
return ret;
}
struct cmp{
bool operator()(const pair<int, int>& p1, const pair<int, int>& p2) {
return p1.first + p1.second < p2.first + p2.second;
}
};
};

【378】 Kth Smallest Element in a Sorted Matrix

【407】 Trapping Rain Water II

【451】 Sort Characters By Frequency

【502】 IPO (2019年2月9日,算法群打卡)

给了一个 n 个项目,每个项目都有一个能力值 capital[i] 和一个利益值 profits[i],一开始有一个初始的能力值 W,要求是从这 n 个项目中选取 k 个项目,每次选取的项目的能力值capital[i]必须小于等于当前的人的能力值。每次做完一个项目,这个项目的利益值就会加在现在的能力值上面。问做完 k 个项目之后,最后能力值最大是多少。

题解:题目不难,重点在于利用heap实现。我们想着把 capital 数组 和 profits 数组综合成一个数组,然后给新的数组排序,排序的方式按照capital从小到大,然后 profits 随意。

然后利用一个 heap, 每次选择一个项目的时候,都把小于当前能力值的项目放进heap,然后从 heap 中弹出一个当前利益值最大的项目,作为当前项目的选择。

时间复杂度是 nlog(n)

 class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
const int n = Profits.size();
vector<pair<int, int>> project(n);
for (int i = ; i < n; ++i) {
project[i] = make_pair(Capital[i], Profits[i]);
}
sort(project.begin(), project.end());
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> pq;
int idx = ;
for (int i = ; i < k; ++i) {
while (idx < n && project[idx].first <= W) {
pq.push(project[idx]);
++idx;
}
if (pq.empty()) { break; }
pair<int, int> p = pq.top();
pq.pop();
W += p.second;
}
return W;
}
struct cmp {
bool operator() (const pair<int, int>& p1, const pair<int, int>& p2) const {
return p1.second < p2.second;
}
};
};

【659】 Split Array into Consecutive Subsequences

【692】 Top K Frequent Words (2018年11月30日)

给了一个string类型的数组 words,在给定整数k,请严格按照出现频率顺序打印出现次数前 k 名的字符串。(出现频率相同的按照字典顺序打印)

题解:用个 unordered_map 存储每个单词出现的次数,然后建立一个小根堆,里面存 k 个pair,(小根堆自定义排序class),然后遍历一遍map,把最后剩下在堆里的 k 个pair的字符串提取出来。

 class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
const int n = words.size();
unordered_map<string, int> mp;
for (auto w : words) { mp[w]++; } priority_queue<pair<string, int>, vector<pair<string, int>>, cmp> pq;
for (auto ele : mp) {
pq.push(ele);
if (pq.size() > k) { pq.pop(); }
}
vector<string> ret(k, "");
int idx = k-;
while (!pq.empty()) {
auto p = pq.top();
pq.pop();
ret[idx--] = p.first;
}
return ret;
}
//自定义比较函数,为啥我想小的排前面要写大于。。
struct cmp {
bool operator()(const pair<string, int> a, const pair<string, int>& b) {
if (a.second == b.second) {
return a.first < b.first;
}
return a.second > b.second;
}
};
};

//自定义比较函数,为啥我想小的排前面要写大于。。(优先队列的自定义比较函数要搞明白,还是不懂啊)

【703】 Kth Largest Element in a Stream

给个数字流,总是返回最大的第K个元素

解法就是用一个只有K个元素的堆,维护这这些数字里面从最大的第K个到最大的元素。

[最小元素...第K大的元素..最大元素], 这个堆总维护后半段的K个

【719】 Find K-th Smallest Pair Distance

【743】 Network Delay Time (2018年12月4日)

一个社交网络里面有 N 个结点,标号为 1 ~ N,给了一个 times 数组,里面的元素 t(u, v, w) 代表从 u结点 到 v结点需要 w 的时间,给了一个源点 K, 问从 K 开始传播一条信息,到每个结点需要至少多少时间,如果从 K 到一个结点不可达,就返回 -1。

题解:floyed求最短路。

 class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
vector<vector<int>> g(N+, vector<int>(N+, INT_MAX));
for (auto t : times) {
int u = t[], v = t[], cost = t[];
g[u][v] = cost;
}
//floyed
for (int f = ; f <= N; ++f) {
for (int i = ; i <= N; ++i) {
g[i][i] = ;
for (int j = ; j <= N; ++j) {
if (g[i][f] != INT_MAX && g[f][j] != INT_MAX) {
g[i][j] = min(g[i][f] + g[f][j], g[i][j]);
}
}
}
}
int ret = INT_MIN;
for (int i = ; i <= N; ++i) {
if (i == K) {continue;}
if (g[K][i] == INT_MAX) {
ret = -;
break;
}
ret = max(ret, g[K][i]);
}
return ret;
}
};

此外,我没看出来跟 heap 有啥关系。

【759】 Employee Free Time

【767】 Reorganize String

【778】 Swim in Rising Water

【786】 K-th Smallest Prime Fraction

【787】 Cheapest Flights Within K Stops (2019年2月9日)

2019年4月6日更新。heap 是个好东西。

给定了一张有向图,还有边的权重,问最多经过K个结点的情况下,从 src 到 dst 的最小花费。

题解:可以用 dijkstra 的思路,只不过这个题多了一个条件是最多经过 K 个结点,那么我们就可以在放入heap的结点中,新增一个纬度,叫做经过的站数。

 //dijkstra 的思路,加上一个K站的条件
class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
vector<vector<int>> graph(n, vector<int>(n, -));
for (int u = ; u < n; ++u) { graph[u][u] = ; }
for (auto& f : flights) {
int u = f[], v = f[], w = f[];
graph[u][v] = w;
}
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq; //{cost, city, how many stops visited}
pq.push({, src, });
while (!pq.empty()) {
auto temp = pq.top(); pq.pop();
int price = temp[], city = temp[], stops = temp[];
if (city == dst) {return price;}
for (int v = ; v < n; ++v) {
if (graph[city][v] == - || city == v) {continue;}
if (stops <= K) {
pq.push({price + graph[city][v], v, stops + });
}
}
}
return -;
}
};

【818】 Race Car

【857】 Minimum Cost to Hire K Workers (2019年3月15日,google tag)

题目给了两个规则让我们设计一个花费最小的办法雇佣K个工人。

  1. Every worker in the paid group should be paid in the ratio of their quality compared to other workers in the paid group. 必须按照unitWage最大的那个工人的unitWage来付所有人的钱。
  2. Every worker in the paid group must be paid at least their minimum wage expectation.

题解:我们考虑如果将wage[i]/quality[i]作为评价指标来进行排序意味着什么?unitWage从小到大排序。 (wisdompeak大佬的题解)

wage[i]/quality[i]最高的那位,意味着最不实惠的工人,它拉高了unitWage,使得其他工人都必须按照这个unitWage乘以各自的quality拿工资.但转念一想,如果我们必须雇佣这个最不实惠的工人的话,那么剩下的工人该如何选择呢?显然我们只要选K-1个quality最低的工人,他们可以拉高那个"最不实惠工人"的quality比重,从而减少其他工人的quality比重,从而降低总工资.

我们再考虑,如果选择了wage[i]/quality[i]第二高的那位,那么我们就在接下来的 N-2 个人里面选择 K-1 个quality最底的工人即可.

由此贪心法的最优策略就出来了.实际操作中,我们根据 wage[i]/quality[i] 从低到高进行处理.

 class Solution {
public:
double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int K) {
int n = quality.size();
vector<pair<double, int>> workers(n);
for (int i = ; i < n; ++i) {
workers[i] = {(double)wage[i]/quality[i], quality[i]};
}
sort(workers.begin(), workers.end());
int totQuality = ;
double res = DBL_MAX;
priority_queue<int, vector<int>, less<int>> pq;
for (int i = ; i < n; ++i) {
double unitWage = workers[i].first;
int qua = workers[i].second;
if (pq.size() == K) {
totQuality -= pq.top();
pq.pop();
}
totQuality += qua;
pq.push(qua);
if (pq.size() == K) {
res = min(res, unitWage * totQuality);
}
}
return res;
}
};

【864】 Shortest Path to Get All Keys

【871】 Minimum Number of Refueling Stops

【882】 Reachable Nodes In Subdivided Graph

【LeetCode】堆 heap(共31题)的更多相关文章

  1. Leetcode 简略题解 - 共567题

    Leetcode 简略题解 - 共567题     写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ...

  2. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  3. JVM的堆(heap)、栈(stack)和方法区(method)

    JVM主要由类加载器子系统.运行时数据区(内存空间).执行引擎以及与本地方法接口等组成.其中运行时数据区又由方法区Method Area.堆Heap.Java stack.PC寄存器.本地方法栈组成. ...

  4. [转]JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )

    这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有比较大的帮助.废话不想讲了.入主题: 先了解具体的概念:JAVA的JVM的内存可分为3个区:堆(h ...

  5. 堆heap和栈Stack(百科)

    堆heap和栈Stack 在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈 ...

  6. (转)Java里的堆(heap)栈(stack)和方法区(method)(精华帖,多读读)

    [color=red][/color]<一> 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收.   引用数据类型,需要用new来创建,既在栈 ...

  7. Java中堆(heap)和栈(stack)的区别

    简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分 ...

  8. 优先队列Priority Queue和堆Heap

    对COMP20003中的Priority queue部分进行总结.图片来自于COMP20003 queue队列,顾名思义特点先进先出 priority queue优先队列,出来的顺序按照优先级prio ...

  9. python数据结构之堆(heap)

    本篇学习内容为堆的性质.python实现插入与删除操作.堆复杂度表.python内置方法生成堆. 区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙:而栈像一个直立垃圾桶,一列下 ...

随机推荐

  1. 学习笔记 - Git

    学习参考网址:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 Git是目前世界上 ...

  2. spark2.2 中文文档

    http://spark.apachecn.org/#/docs/7?id=从-spark-sql-20-升级到-21

  3. CSS二级菜单

    0.需求:当鼠标hover到按钮上时,出现下拉菜单导航条. 1.问题拆解: (1)HTML应该如何组织比较方便合理 因为题中要求下拉菜单位于按钮的正下方,可以使用列表<li>中嵌套无序列表 ...

  4. flutter 添加全局环境变量

    flutter安装好了之后 要添加全局环境变量才可以在终端通过flutter命令来操作 安装flutter环境变量 vim ~/.bash_profile (不存在就创建,添加下面一行命令) expo ...

  5. jQuery.validator.addMethod自定义验证

    jQuery.validator.addMethod("numOrLetter", function(value, element) { return this.optional( ...

  6. CMake下,某些选项的后调整

    编译安卓NDK库时,发现在R15的NDK编译出来的库,总是带了-g选项,导致附带调试,文件过大. 搜索一番后,结论是NDK的文件中有问题: https://github.com/android/ndk ...

  7. JavaScript权威指南(第六版) 初读笔记

    JavaScript的5种原始类型:undefined.null.布尔值.数字和字符串. JavaScript中两个非常重要的数据类型是对象和数组. 通过方括号定义数组元素和通过花括号定义对象属性名和 ...

  8. 由于SID连接不匹配,监听器拒绝连接。

    java.sql.SQLException: Listener refused the connection with the following error:ORA-12505, TNS:liste ...

  9. UML_2_浅谈UML的概念和模型之UML九种图

    转载:https://my.oschina.net/zhumenzhongren/blog/667353 上文我们介绍了,UML的视图,在每一种视图中都包含一个或多种图.本文我们重点讲解UML每种图的 ...

  10. 修改Windows 2008以后系统的NTP服务设置

    @echo off echo autor OAK @echo off echo -------------------------------- @echo off echo setup time r ...