Java中集合的size()的时间复杂度是多少?
我知道,这似乎是一个愚蠢的问题,你可能会认为任何集合上size()的时间复杂度都是O(1)——但我发现我的代码中的“优化”需要调用size()实际上会减慢速度 那么,Java中集合的size()的时间复杂度是多少 我的代码是一个递归算法的实现,用于查找图中的最大团(不重要)。基本上,优化只检查两个集合的大小是否相等(这些集合以任何方式构造),如果大小相等,则只允许再进行一次递归调用(在此之后停止递归) 以下是我的代码的(简化)版本:Java中集合的size()的时间复杂度是多少?,java,size,set,hashset,treeset,Java,Size,Set,Hashset,Treeset,我知道,这似乎是一个愚蠢的问题,你可能会认为任何集合上size()的时间复杂度都是O(1)——但我发现我的代码中的“优化”需要调用size()实际上会减慢速度 那么,Java中集合的size()的时间复杂度是多少 我的代码是一个递归算法的实现,用于查找图中的最大团(不重要)。基本上,优化只检查两个集合的大小是否相等(这些集合以任何方式构造),如果大小相等,则只允许再进行一次递归调用(在此之后停止递归) 以下是我的代码的(简化)版本: private static void rec
private static void recursivelyFindMaximalCliques(Set<Integer> subGraph, Set<Integer> candidates, Set<Integer> notCandidates) {
boolean noFurtherCliques = false;
Iterator<Integer> candidateIterator = candidates.iterator();
while (candidateIterator.hasNext()) {
int nextCandidate = candidateIterator.next();
candidateIterator.remove();
subGraph.add(nextCandidate);
Set<Integer> neighbors = getNeighbors(nextCandidate);
Set<Integer> newCandidates = calculateIntersection(candidates, neighbors);
Set<Integer> newNotCandidates = calculateIntersection(notCandidates, neighbors);
//if (newCandidates.size() == candidates.size())
// noFurtherCliques = true;
recursivelyFindMaximalCliques(subGraph, newCandidates, newNotCandidates);
//if (noFurtherCliques)
// return;
subGraph.set.remove(nextCandidate);
notCandidates.set.add(nextCandidate);
}
}
private static void recursivelyFindMaximalCliques(集合子图、集合候选对象、集合Not候选对象){
布尔派系=假;
迭代器candidateIterator=候选项。迭代器();
while(candidateInterator.hasNext()){
int-nextCandidate=candidateInterator.next();
CandidateInterator.remove();
子图。添加(下一个条件);
设置邻居=获取邻居(nextCandidate);
设置新候选项=计算区间(候选项、邻居);
Set newNotCandidates=calculateIntersection(notCandidates,neights);
//if(newCandidates.size()==candidates.size())
//无派系=正确;
递归查找最大团(子图,newCandidates,newNotCandidates);
//if(无集团)
//返回;
子图.set.remove(nextCandidate);
notCandidates.set.add(nextCandidate);
}
}
我已经注释掉的行是有问题的行-您可以看到它们检查集合newCandidates和candidates是否大小相同,如果大小相同,递归只允许更深一层
当这些行没有注释时,代码运行速度会慢10%——无论使用的集合是HashSet、TreeSet还是LinkedHashSet,都是如此。这毫无意义,因为这些行确保递归调用更少
我唯一可以假设的是,对集合调用size()需要很长时间。在Java中对集合调用size()是否需要比O(1)更长的时间
编辑
因为有人问过,这里是calculateIntersection():
private static IntegerSet calculateIntersection(Set setA,Set setB){
如果(setA.size()==0 | | setB.size()==0)
返回新集合();
Set intersection=new Set();//将其替换为TreeSet、HashSet或LinkedHashSet,以使用的为准
交叉点。addAll(setA);
交叉口。保留(后退);
折返交叉口;
}
第二次编辑
这是完整的代码,如果你喜欢的话。我犹豫是否要发布它,因为它又长又脏,但人们问,所以它在这里:
public class CliqueFindingAlgorithm {
private static class IntegerSet {
public Set<Integer> set = new TreeSet<Integer>(); //Or whatever Set is being used
}
private static ArrayList<IntegerSet> findMaximalCliques(UndirectedGraph graph) {
ArrayList<IntegerSet> cliques = new ArrayList<IntegerSet>();
IntegerSet subGraph = new IntegerSet();
IntegerSet candidates = new IntegerSet();
IntegerSet notCandidates = new IntegerSet();
for (int vertex = 0; vertex < graph.getNumVertices(); vertex++) {
candidates.set.add(vertex);
}
recursivelyFindMaximalCliques(cliques, graph, subGraph, candidates, notCandidates);
return cliques;
}
private static void recursivelyFindMaximalCliques(ArrayList<IntegerSet> cliques, UndirectedGraph graph,
IntegerSet subGraph, IntegerSet candidates, IntegerSet notCandidates) {
boolean noFurtherCliques = false;
Iterator<Integer> candidateIterator = candidates.set.iterator();
while (candidateIterator.hasNext()) {
int nextCandidate = candidateIterator.next();
candidateIterator.remove();
subGraph.set.add(nextCandidate);
IntegerSet neighbors = new IntegerSet();
neighbors.set = graph.getNeighbors(nextCandidate);
IntegerSet newCandidates = calculateIntersection(candidates, neighbors);
IntegerSet newNotCandidates = calculateIntersection(notCandidates, neighbors);
if (newCandidates.set.size() == candidates.set.size())
noFurtherCliques = true;
recursivelyFindMaximalCliques(cliques, graph, subGraph, newCandidates, newNotCandidates);
if (noFurtherCliques)
return;
subGraph.set.remove(nextCandidate);
notCandidates.set.add(nextCandidate);
}
if (notCandidates.set.isEmpty()) {
IntegerSet clique = new IntegerSet();
clique.set.addAll(subGraph.set);
cliques.add(clique);
}
}
private static IntegerSet calculateIntersection(IntegerSet setA, IntegerSet setB) {
if (setA.set.size() == 0 || setB.set.size() == 0)
return new IntegerSet();
IntegerSet intersection = new IntegerSet();
intersection.set.addAll(setA.set);
intersection.set.retainAll(setB.set);
return intersection;
}
公共类cliquefinding算法{
私有静态类整数集{
public Set Set=new TreeSet();//或正在使用的任何集合
}
私有静态ArrayList findMaximalCliques(无向图){
ArrayList cliques=新的ArrayList();
整数集子图=新整数集();
整数集候选者=新整数集();
IntegerSet notCandidates=新的IntegerSet();
对于(int-vertex=0;顶点
}
公共类无向图{
//------------------------------私有变量------------------------------
私人ArrayList邻里主义者;
私人国际努梅德斯;
//------------------------------------常数------------------
//------------------------------构造器------------------------------
公共无向图(整数){
this.neightrlists=新的数组列表(numVertices);
此值为0.numEdges=0;
对于(int i=0;ipublic class CliqueFindingAlgorithm {
private static class IntegerSet {
public Set<Integer> set = new TreeSet<Integer>(); //Or whatever Set is being used
}
private static ArrayList<IntegerSet> findMaximalCliques(UndirectedGraph graph) {
ArrayList<IntegerSet> cliques = new ArrayList<IntegerSet>();
IntegerSet subGraph = new IntegerSet();
IntegerSet candidates = new IntegerSet();
IntegerSet notCandidates = new IntegerSet();
for (int vertex = 0; vertex < graph.getNumVertices(); vertex++) {
candidates.set.add(vertex);
}
recursivelyFindMaximalCliques(cliques, graph, subGraph, candidates, notCandidates);
return cliques;
}
private static void recursivelyFindMaximalCliques(ArrayList<IntegerSet> cliques, UndirectedGraph graph,
IntegerSet subGraph, IntegerSet candidates, IntegerSet notCandidates) {
boolean noFurtherCliques = false;
Iterator<Integer> candidateIterator = candidates.set.iterator();
while (candidateIterator.hasNext()) {
int nextCandidate = candidateIterator.next();
candidateIterator.remove();
subGraph.set.add(nextCandidate);
IntegerSet neighbors = new IntegerSet();
neighbors.set = graph.getNeighbors(nextCandidate);
IntegerSet newCandidates = calculateIntersection(candidates, neighbors);
IntegerSet newNotCandidates = calculateIntersection(notCandidates, neighbors);
if (newCandidates.set.size() == candidates.set.size())
noFurtherCliques = true;
recursivelyFindMaximalCliques(cliques, graph, subGraph, newCandidates, newNotCandidates);
if (noFurtherCliques)
return;
subGraph.set.remove(nextCandidate);
notCandidates.set.add(nextCandidate);
}
if (notCandidates.set.isEmpty()) {
IntegerSet clique = new IntegerSet();
clique.set.addAll(subGraph.set);
cliques.add(clique);
}
}
private static IntegerSet calculateIntersection(IntegerSet setA, IntegerSet setB) {
if (setA.set.size() == 0 || setB.set.size() == 0)
return new IntegerSet();
IntegerSet intersection = new IntegerSet();
intersection.set.addAll(setA.set);
intersection.set.retainAll(setB.set);
return intersection;
}
public class UndirectedGraph {
// ------------------------------ PRIVATE VARIABLES ------------------------------
private ArrayList<TreeMap<Integer, Double>> neighborLists;
private int numEdges;
// ------------------------------ CONSTANTS ------------------------------
// ------------------------------ CONSTRUCTORS ------------------------------
public UndirectedGraph(int numVertices) {
this.neighborLists = new ArrayList<TreeMap<Integer, Double>>(numVertices);
this.numEdges = 0;
for (int i = 0; i < numVertices; i++) {
this.neighborLists.add(new TreeMap<Integer, Double>());
}
}
// ------------------------------ PUBLIC METHODS ------------------------------
public void addEdge(int vertexA, int vertexB, double edgeWeight) {
TreeMap<Integer, Double> vertexANeighbors = this.neighborLists.get(vertexA);
TreeMap<Integer, Double> vertexBNeighbors = this.neighborLists.get(vertexB);
vertexANeighbors.put(vertexB, edgeWeight);
vertexBNeighbors.put(vertexA, edgeWeight);
this.numEdges++;
}
public List<Integer> computeCommonNeighbors(int vertexA, int vertexB) {
List<Integer> commonNeighbors = new ArrayList<Integer>();
Iterator<Integer> iteratorA = this.getNeighbors(vertexA).iterator();
Iterator<Integer> iteratorB = this.getNeighbors(vertexB).iterator();
if (iteratorA.hasNext() && iteratorB.hasNext()) {
int nextNeighborA = iteratorA.next();
int nextNeighborB = iteratorB.next();
while(true) {
if (nextNeighborA == nextNeighborB) {
commonNeighbors.add(nextNeighborA);
if (iteratorA.hasNext() && iteratorB.hasNext()) {
nextNeighborA = iteratorA.next();
nextNeighborB = iteratorB.next();
}
else
break;
}
else if (nextNeighborA < nextNeighborB) {
if (iteratorA.hasNext())
nextNeighborA = iteratorA.next();
else
break;
}
else if (nextNeighborB < nextNeighborA) {
if (iteratorB.hasNext())
nextNeighborB = iteratorB.next();
else
break;
}
}
}
return commonNeighbors;
}
// ------------------------------ PRIVATE METHODS ------------------------------
private class EdgeIterator implements Iterator<int[]> {
private int vertex;
private int[] nextPair;
private Iterator<Integer> neighborIterator;
public EdgeIterator() {
this.vertex = 0;
this.neighborIterator = neighborLists.get(0).keySet().iterator();
this.getNextPair();
}
public boolean hasNext() {
return this.nextPair != null;
}
public int[] next() {
if (this.nextPair == null)
throw new NoSuchElementException();
int[] temp = this.nextPair;
this.getNextPair();
return temp;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void getNextPair() {
this.nextPair = null;
while (this.nextPair == null && this.neighborIterator != null) {
while (this.neighborIterator.hasNext()) {
int neighbor = this.neighborIterator.next();
if (this.vertex <= neighbor) {
this.nextPair = new int[] {vertex, neighbor};
return;
}
}
this.vertex++;
if (this.vertex < getNumVertices())
this.neighborIterator = neighborLists.get(this.vertex).keySet().iterator();
else
this.neighborIterator = null;
}
}
}
// ------------------------------ GETTERS & SETTERS ------------------------------
public int getNumEdges() {
return this.numEdges;
}
public int getNumVertices() {
return this.neighborLists.size();
}
public Double getEdgeWeight(int vertexA, int vertexB) {
return this.neighborLists.get(vertexA).get(vertexB);
}
public Set<Integer> getNeighbors(int vertex) {
return Collections.unmodifiableSet(this.neighborLists.get(vertex).keySet());
}
public Iterator<int[]> getEdgeIterator() {
return new EdgeIterator();
}
//HashSet
public int size() {
return map.size();
}
//Hashmap
public int size() {
return size;
}