如何找到Java向量的停止和启动索引



我有一个向量,看起来像这样:

y =
Columns 1 through 19:
1   1   1   1   1   1   1   1   1   1   1   1   2   2   2   2   2   2   2
Columns 20 through 38:
2   2   2   2   3   3   3   3   3   3   3   3   3   3   3   4   4   4   4
Columns 39 through 57:
4   4   4   4   4   4   4   5   5   5   5   5   5   5   5   5   5   5   6
Columns 58 through 67:
6   6   6   6   6   6   6   6   6   6

向量CCD_ 1总是从1开始并且被向上计数。你可以看到有很多相同的数字。这是样本的类。

这里我们有1 1 1 1 1 1 1 1 1 1 1 1=12个样本,用于类编号1。

对于第2类,我们有2 2 2 2 2 2 2 2 2 2 2=11个样本。

我的问题是,我想找到每节课的开始和结束。例如:类1总是从索引0开始,在本例中,在索引11结束。

第二节课在第一节课结束后直接开始。

问题:

我正在使用EJML(高效Java矩阵库(,并计划使用以下函数:

C = A.extractMatrix(1,4,2,8) 

这等于这个MATLAB代码:

C = A(2:4,3:8) 

但我需要从这个y向量中找到开始和停止索引。第三班在什么索引中停止和开始?你有什么聪明的办法吗?

当然,我可以使用for循环来实现这一点,但Java中的for循环非常慢,因为我将有一个非常非常大的y向量。

建议?

编辑:

这是一个建议。这好吗,还是可以做得更好?

private void startStopIndex(SimpleMatrix y, int c, Integer[] startStop) {
int column = y.numCols();
startStop[0] = startStop[1] + 1; // Begin at the next class
for(int i = startStop[0]; i < column; i++) {
if(y.get(i) != c) {
break;
}else {
startStop[1] = i;
}
}

}

假设我们调用的方法来自:

Integer[] startStop = new Integer[2];
for(int i = 0; i < c; i++) {
startStopIndex(y, c, startStop);
}

如果你想做得更快,那么二进制搜索就是你的朋友。把这些放在一起非常快,它在O(logn(时间内完成任务,就像线性搜索在O(n(中完成的那样。这是非常基本的,假设你的数据看起来和你描述的很像。给它输入奇怪的数据,它就会崩溃。:

int[] breakPoints(int[] arr, int low, int high){
int[] rtrn = new int[high];
for(int i=low;i<high;i++){
rtrn[i]=binarySearch(arr, i, 0, arr.length-1);
}
return rtrn;
}
int binarySearch(int[] arr, int k, int start, int end){
int mid = (start+end)/2;
if(mid==arr.length){
return -1;
}
if(arr[mid]==k && arr[mid+1]==k+1){
return mid+1; //or just mid if you want before breakpoint
}
if(arr[mid]<=k){
return binarySearch(arr, k, mid+1, end);
}
return binarySearch(arr, k, start, mid-1);
}

你可以这样称呼它:

int[] data = {1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,6,6,6,6};
int[] bp = breakPoints(data,1,6);
//return 0, 3, 8, 13, 16, 18 

我想这是有名字的,但我记不清它可能是什么了,但你开始用加速搜索来寻找下一个边界,然后使用二进制搜索。

你知道这些数字是按升序排列的,而且可能有很多相同的数字,所以你从检查下一个元素开始。但你不是一步一步地走,而是加速,然后走2、4、8、16。。。直到你找到一个更高的数字。

一旦你找到了一个更高的数字,你就走得太远了,但最后一步有初始数字,所以你知道边界在最后两步之间,然后对边界进行二进制搜索。

一旦你为边界提供了资金,你就开始重新踩1、2、4。。。用于下一个边界。

如果你希望大多数数字的出现次数大致相同,你可以保持一个跑步平均数,并用这个平均数迈出第一步,开始跑步。

我把它留给你来实际编码。

以下是MATLAB中的内容。for循环将遍历存储在x1中的每个唯一值,然后找到该值的第一次和最后一次出现。

x = [ 1 1 1 2 2 3 3 3 3 3 4 4 4 4 5 5 5 ]
x1 = unique(x)'
for k1 = 1:length(x1)
x1(k1,2:3) = [find(x == x1(k1,1),1,"first"), find(x == x1(k1,1),1,"last")];
end

上述代码产生x1作为3列矩阵

1     1     3
2     4     5
3     6    10
4    11    14
5    15    17

最新更新