Skip to content

Commit 8069b71

Browse files
EdgeAshazl397985856
authored andcommitted
feat: 每日一题 elevator dispatch 2019-07-31 (azl397985856#103)
* feat: longest harmonious subsequence * daily: Longest Harmonious Subsequence, option 1 * alternative solutions. * alternative solutions. * Update 2019-06-20.md * Update 2019-06-20.md * Update 2019-06-20.md * feat: date 2019.06.17 * fix: add tag. * pref: optimize code. * pref: optimize code. * pref: one code for each solution. * feat: 2019-07-31 elevator dispatch * feat: longest harmonious subsequence * alternative solutions. * Update 2019-06-20.md * alternative solutions. * Update 2019-06-20.md * fix: title incorrect. * feat: longest harmonious subsequence * daily: Longest Harmonious Subsequence, option 1 * alternative solutions. * Update 2019-06-20.md * feat: date 2019.06.17 * fix: add tag. * pref: optimize code. * alternative solutions. * Update 2019-06-20.md * Update 2019-06-20.md * pref: optimize code. * pref: one code for each solution. * feat: 2019-07-31 elevator dispatch * pref: more one good solution. * fix: unnecessary change * Update 136.single-number.md * Update 2019-07-31.md
1 parent d6f32e2 commit 8069b71

File tree

2 files changed

+156
-1
lines changed

2 files changed

+156
-1
lines changed

Diff for: daily/2019-07-31.md

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
## 每日一题 - 小飞电梯调度问题
2+
3+
### 信息卡片
4+
5+
- 时间: 2019-07-31
6+
- 题目链接:暂无
7+
- tag:`Math` `Dynamic Programming`
8+
9+
### 题目描述:
10+
11+
```
12+
微软亚洲研究所所在的希格玛大厦一共有6部电梯。在高峰时间,每层都有人上下,电梯在每层都停。实习生小飞常常会被每层都停的电梯弄得很不耐烦,于是他提出了这样一个办法:
13+
由于楼层并不太高看没在繁忙的上下班时间,每层电梯从一层往上走时,我们只允许电梯停在其中的某一层。所有的乘客都从一楼上电梯,到达某层楼后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。
14+
在一楼的时候,每个乘客选择自己的目的层,电梯则自动计算出应停的楼层。
15+
问:电梯停在哪一层楼,能够保证这次乘坐电梯的所有乘客爬楼梯的层数之和最少。
16+
17+
扩展:
18+
19+
1.如何在O(n)的时间复杂度完成?
20+
2.往上爬楼梯,总是比往下走要累的。假设往上爬一个楼层,要耗费k单位的能量,而往下走只需要耗费1单位的能量,那么如果题目条件改为让所有人消耗的能量最少,这个问题怎么解决呢?
21+
这个问题可以用类似上面的分析方法来解答看,因此笔者不再累述,留给读者自行解决。
22+
3.在一个高楼里面,电梯只在某一个楼层停,这个政策还是不太人性化。如果电梯会在k个楼层停呢?读者可以发挥自己的想象力,看看如何寻找最优方案。
23+
```
24+
25+
### 参考答案
26+
27+
28+
题意是
29+
每层都停 => 只停一层,其余让人爬楼梯;所有人爬梯之和最小
30+
选择目的层(i),在i层下的人数是T[i],根据大家选择的目的层计算在哪一层(X)停最优
31+
sum(1~N){T[i]*|i-x|}的最小值
32+
33+
从简单易想到的方式开始;
34+
从1楼开始直到顶层,算出在每层人需要爬梯的总和数组result
35+
找出Min(result)下标
36+
时间复杂度是O(N^2)
37+
38+
```js
39+
/**
40+
* 两个测试数据
41+
* nPerson = [0, 1, 3, 4, 2, 3]
42+
* nPerson = [0, 1, 0, 2, 2, 6]
43+
*/
44+
function original(nPerson) { // nPerson首元素设0,使楼层与下标对应
45+
// nPerson[i] 在i层下的人, N 总楼层
46+
let result = [0]; // 存各层结果
47+
let target = 1; // 最小值下标
48+
for(let x = 1; x < nPerson.length; x++) { // 目标楼层x
49+
result[x]=0;
50+
for(let i = 1; i < nPerson.length; i++) { // 人在哪层停留
51+
result[x] += nPerson[i]*Math.abs(x-i);
52+
}
53+
if(result[target] > result[x]) {
54+
target = x
55+
}
56+
}
57+
return target;
58+
}
59+
```
60+
61+
进一步考虑(动态规划)
62+
假设在i层停,共需要爬Y阶;在i层有N2人,在i层以下共N1人,i层以上共N3人
63+
如果在i-1层停,相比i层变化Y+N2+N3-N1 = Y - (N1-N2-N3) => N1 > (N2 + N3)时会减少爬阶数
64+
如果在i+1层停,相比i层变化Y-N3+N2+N1 = Y - (N3-N2-N1) => N3 > (N2 + N1)时会减少爬阶数
65+
所以在N1 > N2+N3时应该在i-1层停,N3 > N2+N1时应该在i+1层停; 否则在i层停
66+
67+
初始状态电梯停在第一层,向上进行状态的变迁,开始时N2 + N1 - N3 < 0
68+
sum越来越小,直到某一层N2 + N1 >= N3,就没有必要在往上走了。这时已求出最合适的楼层了
69+
70+
```js
71+
function betterOne(nPerson) { // 首元素设空, 下标就与楼层对应了,nPerson的长度-1就是楼层数
72+
let N1 = 0;
73+
let N2 = nPerson[1];
74+
let N3 = 0;
75+
let target = 1;
76+
// 第一层时,算出人需要走的楼梯数Y和在一楼以上的人数N3
77+
for(let i = 2; i < nPerson.length; i++) {
78+
N3 += nPerson[i];
79+
}
80+
// 再来优化
81+
for(let i = 2; i < nPerson.length; i++) {
82+
if (N1+N2 < N3) { // 在i+1层停较优
83+
target = i;
84+
N1 += N2
85+
N3 -= nPerson[i]
86+
N2 = nPerson[i]
87+
} else {
88+
break
89+
}
90+
}
91+
return target
92+
}
93+
```
94+
95+
扩展问题2的解
96+
向上爬比向下走更耗费体力,假设上楼是下楼耗费能量的k倍;k大于1
97+
比较消耗能量的大小决定楼层,只需在动态规划方式上增加权重即可
98+
99+
```js
100+
function betterOnewithWeight(nPerson, k) { // 首元素设空, 下标就与楼层对应了,nPerson的长度-1就是楼层数
101+
let N1 = 0;
102+
let N2 = nPerson[1];
103+
let N3 = 0;
104+
let target = 1;
105+
// 第一层时,算出人需要走的楼梯数Y和在一楼以上的人数N3
106+
for(let i = 2; i < nPerson.length; i++) {
107+
N3 += nPerson[i];
108+
}
109+
// 再来优化
110+
for(let i = 2; i < nPerson.length; i++) {
111+
if (N1+N2 < N3*k) { // 在i+1层停比较好
112+
target = i;
113+
N1 += N2
114+
N3 -= nPerson[i]
115+
N2 = nPerson[i]
116+
} else {
117+
break;
118+
}
119+
}
120+
return target
121+
}
122+
```
123+
124+
### 其他优秀解答
125+
中位数方法
126+
127+
假设两个人在2楼和9楼下。那么在2-9楼之间任意层停,两人走楼梯的层数和是不变的
128+
换一组(第二小、第二大)人也是这么处理
129+
将每个人要去的楼层从低到高逐一排列,找到中位数,此中位数就是最优楼层
130+
131+
时间复杂度O(N)
132+
133+
```js
134+
/**
135+
* 中位数方法
136+
*/
137+
function median(nPerson) {
138+
const newArr = []; // 存楼层
139+
for(let i=0; i < nPerson.length; i++) {
140+
while(nPerson[i] > 0) {
141+
newArr.push(i)
142+
nPerson[i]--
143+
}
144+
}
145+
let len = newArr.length;
146+
// 返回楼层中位数
147+
return len % 2 == 1 ? newArr[(len+1)/2] : newArr[len/2]
148+
}
149+
```

Diff for: daily/README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ tag: `几何`
209209

210210
时间:2019-07-30
211211

212+
### [电梯调度问题](./2019-07-31.md)
213+
214+
tag: `Math` `Dynamic Programming`
215+
216+
时间:2019-07-31
217+
212218
### [105.从前序与中序遍历序列构造二叉树](./2019-08-05.md)
213219

214220
tag: `Tree` `Array`
@@ -241,7 +247,7 @@ tag: `并查集` `BFS`
241247

242248
### [771.jewels-and-stones](./2019-08-22.md)
243249

244-
tag:String` `Hash Table`
250+
tag:`String` `Hash Table`
245251

246252
时间: 2019-08-22
247253

0 commit comments

Comments
 (0)