Java 如何快速地将一个元素插入到数组中,在所有相等的元素之后插入重复的元素?

Java 如何快速地将一个元素插入到数组中,在所有相等的元素之后插入重复的元素?,java,algorithm,Java,Algorithm,我有一个ArrayList,其中包含按“Z”(浮动)位置从低到高排序的游戏对象。我不确定ArrayList是否是最好的选择,但我提出了这样一种解决方案,可以在复杂度高于线性的情况下(最坏情况)找到插入索引: GameObject go=new GameObject(); int指数=0; int start=0,end=displayList.size();//displayList是ArrayList while(结束-开始>0) { 索引=(开始+结束)/2; if(go.depthZ>=d

我有一个ArrayList,其中包含按“Z”(浮动)位置从低到高排序的游戏对象。我不确定ArrayList是否是最好的选择,但我提出了这样一种解决方案,可以在复杂度高于线性的情况下(最坏情况)找到插入索引:

GameObject go=new GameObject();
int指数=0;
int start=0,end=displayList.size();//displayList是ArrayList
while(结束-开始>0)
{
索引=(开始+结束)/2;
if(go.depthZ>=displayList.get(index.depthZ)
开始=索引+1;
else if(go.depthZ0&&go.depthZ=displayList.get(index.depthZ)
索引++;
问题在于,必须将元素插入到元素链中的特定位置,并在该链的末端具有相同的depthZ值。这就是为什么我需要在二进制搜索之后再加上两个while循环,我认为这不会太贵,因为二进制搜索给了我这个位置的近似值


我仍然在想,对于这样的问题,是否有更好的解决方案或一些我从未听说过的已知算法?可能使用与ArrayList不同的数据结构?目前,我忽略了最坏情况下的插入O(n)(在开头或中间插入),因为使用普通列表,我无法使用上述方法找到要插入的索引。

将1添加到键的最低有效字节(带进位);对插入位置的二进制搜索;然后把它插进去


二进制搜索的构造必须使其在重复序列的最左边结束,但考虑到对各种二进制搜索算法的理解,这是微不足道的。

您应该尝试使用平衡搜索树(例如红黑树)而不是数组。首先,您可以尝试使用
TreeMap
witch在内部使用一棵红黑树来查看它是否满足您的要求。可能的实施:

Map<Float, List<Object>> map = new TreeMap<Float, List<Object>>(){
    @Override
    public List<Object> get(Object key) {
        List<Object> list = super.get(key);
        if (list == null) {
            list = new ArrayList<Object>();
            put((Float) key, list);
        }
        return list;
    }
};

一种方法是执行减半搜索,其中第一次搜索是通过列表的一半(list.size()/2),然后下一次可以执行其中的一半,依此类推。使用这种指数方法,当您有4096个对象时,您不必进行4096次搜索,而只需要12次搜索


对不起,我完全无视技术术语,我在术语方面不是最好的:p

除非我忽略了什么,否则你的方法基本上是正确的(但有一个错误,见下文),在这个意义上,您的第一个while尝试计算插入索引,以便将其放在所有较低或相等的Z之后:在您的第一个测试中正确地有一个等号(如果它产生TRUE,则更新“start”)

然后,当然,没有必要再担心它在平等中的地位。然而,您的后续while破坏了这种良好的情况:第一次后续while中的测试总是正确的(一次),因此您返回;然后你需要第二次跟进来撤销它。所以,你应该删除两个跟进,然后你就完成了

然而,你的第一个while有一个小问题,因此它并不总是完全达到目的。我猜是错误的结果促使你在“修复”这一问题的同时实施后续行动

这是你这段时间的问题。假设您有一个try索引(start+end)/2,它指向一个更大的Z,但正好在它有值Z之前。然后进入第二个测试(elseif)并将“end”设置为该Z值所在的位置。最后,你会得到一个准确的位置。 补救方法很简单:在elseif赋值中,输入“end=index”(不带-1)。最后一句话:elseif中的测试是不必要的,否则就足够了

那么,你得到的一切

GameObject go = new GameObject();
int index = 0;
int start = 0, end = displayList.size(); // displayList is the ArrayList
while(end - start > 0)
{
    index = (start + end) / 2;
    if(go.depthZ >= displayList.get(index).depthZ)
        start = index + 1;
    else
        end = index;
}

(我希望我没有忽略一些琐碎的事情…

为什么不使用
HashMap
或类似的东西,并映射到每个值,出现的次数?啊,对不起,忘了提到DEXTHZ值是浮动的,所以在数组的中间插入太多可能的值是昂贵的,因此不会带来二进制搜索的速度。您可以根据需要使用
TreeMap
。顺便说一句,
float
s的值与
int
s的值没有区别,因为它们都是4字节的。您的建议称为二进制搜索,OP已经做到了:
index=(start+end)/2阿当,我没看到,sorry@downvoter如果你不明白,问吧。这是一个标准的技巧。@BogdanEmilMariesan你不理解的答案和“不是答案”之间有很大的区别。这里没有批评问题或寻求澄清的东西,但有一个算法规范,而且一直都是这样。你的评论仍然不可理解。无关紧要。它之所以出现,是因为你投了“没有答案”的票,而且它以黑白相间的形式出现,上面写着你的名字。除非你删除它,否则它将被所有人视为你观点的表达。包括我在内。
map.get(0.5f).add("hello");
map.get(0.5f).add("world");
map.get(0.6f).add("!");
System.out.println(map);
GameObject go = new GameObject();
int index = 0;
int start = 0, end = displayList.size(); // displayList is the ArrayList
while(end - start > 0)
{
    index = (start + end) / 2;
    if(go.depthZ >= displayList.get(index).depthZ)
        start = index + 1;
    else
        end = index;
}