在线算法 & 离线算法
一.概念
-
离线算法:
算法设计策略都是基于在执行算法前输入数据已知的基本假设,也就是说,算法在求解问题已具有与该问题相关的完全信息,通常将这类具有问题完全信息前提下设计出的算法成为离线算法( off line algorithms) -
在线算法:
- 在计算机科学中,一个在线算法是指它可以以序列化的方式一个个的处理输入,也就是说在开始时并不需要已经知道所有的输入。
相对的,对于一个离线算法,在开始时就需要知道问题的所有输入数据,而且在解决一个问题后就要立即输出结果。例如,选择排序在排序前就需要知道所有待排序元素,然而插入排序就不必。 - 因为在线算法并不知道整个的输入,对在线算法的研究主要集中在当前环境下怎么做出选择,在线算法找到的解只是局部最优解而无法保证整体最优。
- 对相同问题的在线算法和离线算法的对比分析形成了以上观点。如果想从其他角度了解在线算法可以看一下 流算法(关注精确呈现过去的输入所使用的内存的量),动态算法(关注维护一个在线输入的结果所需要的时间复杂度)和在线机器学习。
二.对称移动算法:
package util;
/**
* @projName: algorithm
* @packgeName: util
* @className: SymMoveLine
* @author: pentiumCM
* @email: [email protected]
* @date: 2020/1/7 19:41
* @describe: 对称移动算法-直线上的K服务问题
*/
public class SymMoveLine {
//直线上的k服务问题中:请求序列和服务车的位置使用横坐标点来表示
/**
* 初始化k个服务车的横坐标的序列,k服务车的序列是升序排列的
*
* @return 返回初始化后k个服务车的横坐标
*/
public static int[] initServices() {
int[] kServices = {1, 3};
return kServices;
}
/**
* 初始化服务请求序列的的横坐标
*
* @param n 服务请求序列的长度
* @return 返回初始化后的服务请求序列的横坐标
*/
public static int[] initRequests(int n) {
int[] requests = new int[n];
for (int i = 0; i < n; i++) {
//给服务请求序列的奇数为赋值0,偶数位赋值1, 即服务请求序列为:0,1,0,1,0,1......
requests[i] = (i % 2 == 0) ? 0 : 1;
}
return requests;
}
/**
* 对称移动算法---解决直线上的k服务问题
*
* @param kServices k个服务车的横坐标
* @param requests 服务请求序列的横坐标
* @return 返回k个服务车移动的总距离
*/
public static int symMoveAlgoLine(int[] kServices, int[] requests) {
int dists = 0;
int reqsNum = requests.length;
int kServiceNum = kServices.length;
for (int t = 0; t < reqsNum; t++) {
int reqT = requests[t];
int d = 0;
//1. 所有的服务位于Rt的同一侧: 选距Xt最近的服务si向Rt移动距离 d = |si - Rt|
//请求在最左边
if (reqT < kServices[0]) {
//服务车1移动的距离为d
d = kServices[0] - reqT;
System.out.println("服务车位置移动 s1: " + kServices[0] + " -> " + reqT + " ; s2:不移动" + " --移动了" + d);
//服务1移动到该请求的位置
kServices[0] = reqT;
}
//请求在最右边
else if (reqT > kServices[kServiceNum - 1]) {
//服务车2移动的距离为d
d = kServices[kServiceNum - 1] - reqT;
System.out.println("服务车位置移动 s1:不移动 ; s2: " + kServices[kServiceNum - 1] + " -> " + reqT + " --移动了" + d);
//最右边服务移动到该请求的位置
kServices[kServiceNum - 1] = reqT;
}
//2. 请求Rt位于服务si,sj之间: si、sj同时向Rt移动距离 d = min{|si - Rt, sj - Rt|}
else {
for (int i = 0; i < kServiceNum - 1; i++) {
if (reqT > kServices[i] && reqT < kServices[i + 1]) {
int dl = Math.abs(kServices[i] - reqT);
int dr = Math.abs(kServices[i + 1] - reqT);
//左边服务靠请求更近
if (dl < dr) {
d = dl * 2;
int rposi = kServices[i + 1] - dl;
System.out.println("服务车位置移动 s1: " + kServices[i] + " -> " + reqT +
" ; s2: " + kServices[i + 1] + " -> " + rposi + " --移动了" + d);
//左边的服务移动请求的位置
kServices[i] = reqT;
//右边的服务向请求移动d
kServices[i + 1] -= dl;
}
//右边服务靠请求近
else if (dr > dr) {
d = dr * 2;
int lposi = kServices[i] + dl;
System.out.println("服务车位置移动 s1: " + kServices[i] + " -> " + lposi +
" ; s2: " + kServices[i + 1] + " -> " + reqT + " --移动了" + d);
//左边的服务移动请求的位置
kServices[i] += dr;
//右边的服务向请求移动d
kServices[i + 1] = reqT;
}
//两边服务靠请求一样近
else {
d = dl + dr;
System.out.println("服务车位置移动 s1: " + kServices[i] + " -> " + reqT +
" ; s2: " + kServices[i + 1] + " -> " + reqT + " --移动了" + d);
//左边的服务移动请求的位置
kServices[i] = reqT;
//右边的服务移动请求的位置
kServices[i + 1] = reqT;
}
}
}
}
dists += d;
}
return dists;
}
public static void main(String[] args) {
//初始化k服务车的初始横坐标
int[] kServices = initServices();
//请求序列的横坐标
int[] requests = initRequests(10);
//调用对称移动算法,获取服务车移动的总距离
int dist = symMoveAlgoLine(kServices, requests);
System.out.println("移动的总距离为:" + dist);
}
}