Description
给出n个数,求每个数和它前面每个数的差值绝对值的最小值之和。
n<=32767
比如输入1,2,3,4,5
那么输出就是1+1+1+1 = 4
min(2-1)+min(3-2,2-1)+min(4-3,4-2,4-1)+min(5-4...)
再比如1,4,5,3
min(4-1)+min(5-4,5-1)+min(ab(3-5),ab(3-4),3-1));
= 3+ 1+ 1 = 5;
求解思路相当简单,如果你使用双向链表的话。
获得当前值,然后前驱,求取和这个值的差值。对所有值用一个单项链表去存储。然后统计单项链表的sum值。
所以,我们需要派生一个双向接口,关于双向接口的设计,请参考第四章。
来看主函数做了哪些事情:
public static void main(String[] args) throws IOException {
Random random = new Random();
int[] data = new int[4];
data[0] = 1;
data[1] = 4;
data[2] = 5;
data[3] = 3;
//定义一个统计表
RevenueTable table = new RevenueTable(data[0]);
//将数据加载到表中
for (int i =1;i<data.length;i++){
table.add(new IntDoubleDirElement(data[i]));
}
//遍历统计
table.traverse();
System.out.println("sum = "+table.sum);
}
这一步很好理解,相当于我们将数据加载到了表中。
来看Tranverse函数,我们做了啥?
我们在这个函数里面做了一个遍历,相当于一个迭代器。
时间复杂度很容易计算就是o(n)。
然后我们来看下operation函数:
public int sum;
@Override
public void operation(IntDoubleDirElement intDoubleDirElement) {
IntDoubleDirElement selectElement = intDoubleDirElement.getNext();
SumLineTable t1 = new SumLineTable();
while (selectElement!= null) {
if (selectElement.getLast()!= null){
int dfValue = selectElement.getValue() - selectElement.getLast().getValue();
dfValue = Math.abs(dfValue);
t1.add(new LineElement(dfValue));
}
selectElement = selectElement.getLast();
}
sum+= t1.min();
}
IntDoubleDirElement这个数据的定义在第四章里面做了介绍,就是一个简单的元素
然后是SumLineTable,继承了单链表,然后新增了一个函数
public class SumLineTable extends LineTable {
public int sum(){
int sumValue = 0;
LineElement element = head();
while (element!= null){
sumValue+= element.getValue();
element = element.getNext();
}
return sumValue;
}
public int min(){
if (head() == null)
return 0;
int min = head().getValue();
LineElement selectElement = head();
while (selectElement!= null){
if (min>selectElement.getValue()){
min = selectElement.getValue();
}
selectElement = selectElement.getNext();
}
return min;
}
}
然后就很简单了。
时间复杂度就是第一个while的o(n)
另外一个就是
也是o(n)
所以时间复杂度是o(2n)
operation是在tranverse函数里面进行操作的,时间复杂度是o(2n^2) = o(n^2)
应用的不多。