抄书问题之二
2015-11-29 12:41
447 查看
Given n books( the page number of each book is the same) and an array of integer with size k means k people to copy
the book and the i th integer is the time i th person to copy one book). You must distribute the continuous id books to one people to copy. (You can give book A[1],A[2] to one people, but you cannot give book A[1], A[3] to one people, because book A[1] and
A[3] is not continuous.) Return the number of smallest minutes need to copy all the books.
样例
Given n =
=
Return
spends 3 minutes to copy book 1, Second person spends 4 minutes to copy book 2 and 3, Third person spends 4 minutes to copy book 4. )
解题思路:
1.二分法,最优解。
2 动态规划,时间复杂度很高O(N2 × K)。
class Solution {
public:
/**
* @param n: an integer
* @param times: a vector of integers
* @return: an integer
b0f5
*/
// V1 二分法 (最优解)
int copyBooksII(int n, vector<int> ×) {
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//找出抄书时间的上下限
// 所有人以最快速度抄书,得到下限
// 所有人以最慢速度抄书,得到上限
int lowBound = numeric_limits<int>::max();
int highBound = numeric_limits<int>::min();
for(int i = 0; i < k; i++){
lowBound = min(lowBound, times[i]);
highBound = max(highBound, times[i]);
}
lowBound = lowBound * (( n + k - 1) / k);
highBound = highBound * (( n + k - 1) / k);
// 这里需要排序,将速度最快的排在前面,这样便于canCopy判断
sort(times.begin(), times.end());
// 二分法找出答案,每次二分时判断间值是否能在target时间内抄完
while(lowBound < highBound){
int mid = lowBound + (highBound - lowBound)/2;
if(canCopy(mid, n, times)){
highBound = mid;
}
else{
lowBound = mid + 1;
}
}
return lowBound;
}
// 判断是否能在target时间内抄写完成
// 优先选择最快的人抄写,因此事前需要对times 排序。
// 抄写速度最快的人尽量多抄
bool canCopy(int target, int n, vector<int> ×){
int totalBookCount = n;
int sum = 0;
int i = 0;
while(i < times.size()){
if(sum + times[i] <= target){
sum += times[i];
}
else if (i != (times.size() - 1) &&
times[++i] <= target){
sum = times[i];
}
else {
return false;
}
totalBookCount--;
if(totalBookCount <= 0){
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// V2 : DP, time limit exceeded O(N2 * K)
int copyBooksII1(int n, vector<int> ×) {
// write your code here
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//f[i][j] 表示i个人抄j本书的最小耗时
vector<vector<int> > f(k+1, vector<int>(n+1, 0));
for(int j = 1; j <= n; j++){
f[0][j] = numeric_limits<int>::max();
f[1][j] = times[0] * j;
}
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
int minTime = numeric_limits<int>::max();
for(int x = 0; x <= j; x++){
minTime = min(minTime,
max(f[i-1][x], (j - x) * times[i-1]));
}
f[i][j] = minTime;
}
}
return f[k]
;
}
//V3 : DP 优化, 滚动数组空间优化,但是时间复杂度仍然比较高
int copyBooksII2(int n, vector<int> ×) {
// write your code here
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//f[i][j] 表示i个人抄j本书的最小耗时
vector<vector<int> > f(2, vector<int>(n+1, 0));
for(int j = 1; j <= n; j++){
f[0][j] = numeric_limits<int>::max();
}
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
int minTime = numeric_limits<int>::max();
for(int x = j; x >= 0; x--){
minTime = min(minTime,
max(f[(i-1)%2][x], (j - x) * times[i-1]));
if(f[(i-1)%2][x] < (j - x) * times[i-1]){
break;
}
}
f[i%2][j] = minTime;
}
}
return f[k%2]
;
}
};
the book and the i th integer is the time i th person to copy one book). You must distribute the continuous id books to one people to copy. (You can give book A[1],A[2] to one people, but you cannot give book A[1], A[3] to one people, because book A[1] and
A[3] is not continuous.) Return the number of smallest minutes need to copy all the books.
样例
Given n =
4, array A
=
[3,2,4], .
Return
4( First person
spends 3 minutes to copy book 1, Second person spends 4 minutes to copy book 2 and 3, Third person spends 4 minutes to copy book 4. )
解题思路:
1.二分法,最优解。
2 动态规划,时间复杂度很高O(N2 × K)。
class Solution {
public:
/**
* @param n: an integer
* @param times: a vector of integers
* @return: an integer
b0f5
*/
// V1 二分法 (最优解)
int copyBooksII(int n, vector<int> ×) {
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//找出抄书时间的上下限
// 所有人以最快速度抄书,得到下限
// 所有人以最慢速度抄书,得到上限
int lowBound = numeric_limits<int>::max();
int highBound = numeric_limits<int>::min();
for(int i = 0; i < k; i++){
lowBound = min(lowBound, times[i]);
highBound = max(highBound, times[i]);
}
lowBound = lowBound * (( n + k - 1) / k);
highBound = highBound * (( n + k - 1) / k);
// 这里需要排序,将速度最快的排在前面,这样便于canCopy判断
sort(times.begin(), times.end());
// 二分法找出答案,每次二分时判断间值是否能在target时间内抄完
while(lowBound < highBound){
int mid = lowBound + (highBound - lowBound)/2;
if(canCopy(mid, n, times)){
highBound = mid;
}
else{
lowBound = mid + 1;
}
}
return lowBound;
}
// 判断是否能在target时间内抄写完成
// 优先选择最快的人抄写,因此事前需要对times 排序。
// 抄写速度最快的人尽量多抄
bool canCopy(int target, int n, vector<int> ×){
int totalBookCount = n;
int sum = 0;
int i = 0;
while(i < times.size()){
if(sum + times[i] <= target){
sum += times[i];
}
else if (i != (times.size() - 1) &&
times[++i] <= target){
sum = times[i];
}
else {
return false;
}
totalBookCount--;
if(totalBookCount <= 0){
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// V2 : DP, time limit exceeded O(N2 * K)
int copyBooksII1(int n, vector<int> ×) {
// write your code here
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//f[i][j] 表示i个人抄j本书的最小耗时
vector<vector<int> > f(k+1, vector<int>(n+1, 0));
for(int j = 1; j <= n; j++){
f[0][j] = numeric_limits<int>::max();
f[1][j] = times[0] * j;
}
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
int minTime = numeric_limits<int>::max();
for(int x = 0; x <= j; x++){
minTime = min(minTime,
max(f[i-1][x], (j - x) * times[i-1]));
}
f[i][j] = minTime;
}
}
return f[k]
;
}
//V3 : DP 优化, 滚动数组空间优化,但是时间复杂度仍然比较高
int copyBooksII2(int n, vector<int> ×) {
// write your code here
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//f[i][j] 表示i个人抄j本书的最小耗时
vector<vector<int> > f(2, vector<int>(n+1, 0));
for(int j = 1; j <= n; j++){
f[0][j] = numeric_limits<int>::max();
}
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
int minTime = numeric_limits<int>::max();
for(int x = j; x >= 0; x--){
minTime = min(minTime,
max(f[(i-1)%2][x], (j - x) * times[i-1]));
if(f[(i-1)%2][x] < (j - x) * times[i-1]){
break;
}
}
f[i%2][j] = minTime;
}
}
return f[k%2]
;
}
};
相关文章推荐
- Cocoapods的配置
- java继承深入解析
- 基于Karma和Jasmine的AngularJS测试
- 何时使用copy,strong,weak,assign关键字 定义属性
- C#与C++的混合编程 之二 使用非托管dll 导出标准函数
- TextInputLayout 样式设置
- Java-文件操作与随机访问文件
- BNUOJ 44584 平面切割者
- 线性方程求解之 二范数类型
- UIView的常用方法及相关属性
- 基于tcp raw socket实现的端到端rtt,丢包率检测程序(1)
- Ubuntu 14.04 server 设置mysql允许远程访问
- ShaderForge-随机方形噪点、01循环、贴图位移
- 用python玩转selenium:3-selenium常用操作
- 用python玩转selenium:2-入门实例及分析
- Tsung指南[荐]
- 大数加减
- PHP可变函数学习小结
- 用python玩转selenium:1-准备环境
- 将Android studio 项目导入eclipse的学习过程