Java 如何提高这种嵌套循环算法的时间复杂度?
输入:Java 如何提高这种嵌套循环算法的时间复杂度?,java,algorithm,performance,time-complexity,nested-loops,Java,Algorithm,Performance,Time Complexity,Nested Loops,输入: K = 2; T = [1, 4, 4, 3, 1, 2, 6]; E = [1, 2, 3, 4, 5, 6, 7] 给定一个整数数组T=[t0,t1,t2,…tk]表示一行,其中每个元素是最大等待时间。以及表示所有可能过期时间的数组E=[e0,e1,e2,…ei]。最后,给出了一个整数K,它是容器的最大大小 问题: 对于每个过期时间E,必须获得能够进入大小为K的容器的最后一个元素T的位置,并且T中的每个等待时间必须大于或等于过期时间E,才能进入容器 示例案例1: 输入: K = 2
K = 2; T = [1, 4, 4, 3, 1, 2, 6]; E = [1, 2, 3, 4, 5, 6, 7]
给定一个整数数组T=[t0,t1,t2,…tk]
表示一行,其中每个元素是最大等待时间。以及表示所有可能过期时间的数组E=[e0,e1,e2,…ei]
。最后,给出了一个整数K
,它是容器的最大大小
问题:
对于每个过期时间E
,必须获得能够进入大小为K的容器的最后一个元素T
的位置,并且T
中的每个等待时间必须大于或等于过期时间E
,才能进入容器
示例案例1:
输入:
K = 2; T = [1, 4, 4, 3, 1, 2, 6]; E = [1, 2, 3, 4, 5, 6, 7]
输出:
Kth = [2, 3, 3, 3, 0, 0, 0]
说明:
在E[0]
中,过期时间为1,因此第二行T
将是最后一个进入容器的,因此Kth[0]=2nd
在E[1]
中,过期时间为2,因此第三行T
将是自第一个元素过期以来最后一个进入容器的元素,因此Kth[1]=3rd
在E[2]
中,过期时间为3,因此第三行T
将是自第一个元素过期以来最后一个进入容器的元素,因此Kth[2]=3rd
在E[3]
中,过期时间为4,因此第三行T
将是自第一个元素过期以来最后一个进入容器的元素,因此Kth[3]=3rd
在E[4]
中,过期时间为5,在这种情况下,除了最后一个T
的几乎所有元素都已过期,但是,由于无法完成容器,它必须返回位置0,因此Kth[4]=0
对于E[5]
和E[6]
,依此类推
下面是我能够想到的代码,但它在O(E*T)时间内运行,这对于性能限制来说太慢了:
public static List<Integer> kthElement(int k, List<Integer> T, List<Integer> E) {
List<Integer> kthElements = new ArrayList<>();
for (int i = 0; i < E.size(); i++) {
System.out.println(E.get(i));
int currentElement = 0;
int elementsFilled = 0;
for (int j = 0; j < T.size(); j++) {
if (elementsFilled >= k || k > T.size()) {
break;
}
if (T.get(j) >= E.get(i)) {
elementsFilled++;
currentElement = j + 1;
}
}
if (elementsFilled >= k) {
kthElements.add(currentElement);
} else {
kthElements.add(0);
}
}
return kthElements;
}
公共静态列表kthellement(int k,List T,List E){
List kthElements=new ArrayList();
对于(int i=0;i=k | | k>T.size()){
打破
}
如果(T.get(j)>=E.get(i)){
元素填充++;
currentElement=j+1;
}
}
如果(元素填充>=k){
添加(当前元素);
}否则{
增加(0);
}
}
归还设备;
}
如何提高该算法的性能?我认为用O(E+T)而不是O(E x T)可以很容易地做到这一点 这个循环非常简单,由于嵌套,乍一看似乎是O(E x T),但是内部循环在外部循环中永远不会重置,所以它确实是O(E+T) 在下面的代码中,我将假设E<65536
List<Integer> out = new ArrayList<>();
int inPos = 0;
int kCnt = 0;
int last = 0;
int[] kTracker = new int[65536];
for (int i = 0; i < E.size(); i++)
{
// Remove Expired
kCnt -= kTracker[i];
// Fill Container
while (kCnt < K && inPos < T.length)
{
int exp = i + T.get(inPos);
if (exp < kTracker.length)
{
// don't bother tracking if > E.max, as it won't affect the output.
kTracker[exp]++;
}
last = inPos;
kCnt++;
inPos++;
}
// record output
out.add(last);
}
最后,如果我们对输入没有任何保证,我们可以使用HashMap替换跟踪数组。由于HashMap将为每个元素执行内存分配,它将比上述两种解决方案慢得多,但它可以不受限制地处理各种输入
List<Integer> out = new ArrayList<>();
int inPos = 0;
int kCnt = 0;
int last = 0;
Map<Integer, Integer> kTracker = new HashMap<>();
for (int i = 0; i < E.size(); i++)
{
// Remove Expired
Integer removed = kTracker.remove(i);
if (removed != null)
{
kCnt -= removed;
}
// Fill Container
while (kCnt < K && inPos < T.length)
{
kTracker.put(i + T.get(inPos), kTracker.getOrDefault(i + T.get(inPos), 0) + 1);
last = inPos;
kCnt++;
inPos++;
}
// record output
out.add(last);
}
List out=new ArrayList();
int-inPos=0;
int-kCnt=0;
int last=0;
Map kTracker=newhashmap();
对于(int i=0;i
首先对数组进行排序-然后你可以在找到匹配项后立即停止搜索…@Randy当我对ArrayList进行排序时,我丢失了原始位置,我需要推断第k个元素的返回顺序。如果你需要原始索引,你可以始终创建一个新的int[][]它包含值和索引,然后根据值对其进行排序。这样,您将拥有原始索引。