Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在O(logn)时间复杂度下解决这个问题_Java_Arrays_Data Structures - Fatal编程技术网

Java 如何在O(logn)时间复杂度下解决这个问题

Java 如何在O(logn)时间复杂度下解决这个问题,java,arrays,data-structures,Java,Arrays,Data Structures,问题陈述:给定已排序的整数数组,从给定数组中查找非重复整数。数组中只有1个非重复整数,另一个整数范围为2 输入:[1,1,2,2,4,5,5] 产出:4 输入:[10,10,12,12,15,15,16,18,18] 产出:16 有谁能帮我解决这个时间复杂度为O(logn)的问题吗 注意:N是数组的长度更新 有人指出,原始代码将获取数组的切片,如果通过副本执行,则会使复杂性O(n)。下面是使用指向数组的指针的代码版本: 爪哇: Python: def singleton(arr, lo, hi)

问题陈述:给定已排序的整数数组,从给定数组中查找非重复整数。数组中只有1个非重复整数,另一个整数范围为2

输入:[1,1,2,2,4,5,5] 产出:4

输入:[10,10,12,12,15,15,16,18,18] 产出:16

有谁能帮我解决这个时间复杂度为O(logn)的问题吗


注意:N是数组的长度

更新

有人指出,原始代码将获取数组的切片,如果通过副本执行,则会使复杂性
O(n)
。下面是使用指向数组的指针的代码版本:

爪哇:

Python:

def singleton(arr, lo, hi):
    if (hi == lo):
        return arr[hi]
    m = (hi + lo) // 2
    if (m % 2 == 1):
        if (arr[m] == arr[m-1]):
            return singleton(arr, m+1, hi)
        if (arr[m] != arr[m+1]):
            return arr[m]
        return singleton(arr, lo, m-1);
    else:
        if (arr[m] == arr[m+1]):
            return singleton(arr, m+2, hi)
        if (arr[m] != arr[m-1]):
            return arr[m]
        return singleton(arr, lo, m);
原始答案

因为您知道数组中的所有其他整数正好出现两次,所以可以进行二进制搜索以查找只出现一次的值。您需要查找数组的中点,并确定单例是发生在该数字之前、之后还是该数字。如果是在之前或之后,则继续搜索,但仅搜索数组的该部分(最多一半)。这是
O(logn)
。在python中(注意:当我最初回答这个问题时,它没有标记为
java
——我随后在下面添加了一个java解决方案),您可以将其实现为:

def singleton(arr):
    m = len(arr) // 2
    if (m == 0):
        return arr[0]
    if m % 2 == 1:
        if arr[m] == arr[m-1]:
            return singleton(arr[m+1:])
        if arr[m] != arr[m+1]:
            return arr[m]
        return singleton(arr[:m])
    else:
        if arr[m] == arr[m+1]:
            return singleton(arr[m+2:])
        if arr[m] != arr[m-1]:
            return arr[m]
        return singleton(arr[:m+1])
示例用法:

print(singleton([1,1,2,2,4,5,5]))
print(singleton([10,10,12,12,15,15,16,18,18]))
print(singleton([1,2,2,5,5,6,6,7,7]))
print(singleton([1,1,2,5,5,6,6,7,7]))
print(singleton([10,10,12,12,15,15,16,16,18]))
输出:

4
16
1
2
18
我不是java专家,因此这可能不是最有效的方法,但它确实有效:

public static int singleton(int[] arr) {
    int m = arr.length / 2;
    if (m == 0) return arr[0];
    if (m % 2 == 1) {
        if (arr[m] == arr[m-1]) return singleton(Arrays.copyOfRange(arr, m+1, arr.length));
        if (arr[m] != arr[m+1]) return arr[m];
        return singleton(Arrays.copyOfRange(arr, 0, m));
    }
    else {
        if (arr[m] == arr[m+1]) return singleton(Arrays.copyOfRange(arr, m+2, arr.length));
        if (arr[m] != arr[m-1]) return arr[m];
        return singleton(Arrays.copyOfRange(arr, 0, m+1));
    }
}      
    
public static void main(String args[])
{
    System.out.println(singleton(new int[]{ 1,1,2,2,4,5,5 }));
    System.out.println(singleton(new int[]{ 10,10,12,12,15,15,16,18,18 }));
    System.out.println(singleton(new int[]{1,2,2,5,5,6,6,7,7}));
    System.out.println(singleton(new int[]{1,1,2,5,5,6,6,7,7}));
    System.out.println(singleton(new int[]{10,10,12,12,15,15,16,16,18}));
}

我认为应该还有一个限制。也许是关于元素的数量和它们的范围之间的关系。@LiorKogan已经更新了我忽略约束的语句。你没有说明N是什么。请在问题中说明。我假设N是数组的长度,尽管这只是一个猜测。在这种情况下,您不可能在O(logn)中解决这个问题。这并没有足够的时间来检查数组中的每个元素-唯一可行的方法是在不检查每个元素的情况下找到元素。但是数组被排序的事实并不能真正帮助查找非重复元素。是什么让你认为O(logn)中有一个解决方案?@Stef因为所有其他数字正好出现两次,你可以对单个值进行二进制搜索,即
O(logn)
你能帮助java吗solution@dev_mg99请参阅我的编辑。代码即使不是最有效的,也是功能性的。感谢这个解决方案,我在这个“arr[m+1:]”中有点困惑,所以我要求使用java解决方案。@dev_mg99不用担心-在我第一次回答问题时,您没有标记这个问题,所以我只使用了子数组更容易编写的语言。我希望java代码能够清楚地说明
arr[m+1://code>的含义(从索引
m+1
到结尾的
arr
子数组),感谢您提供了一个非常好的解决方案。但在时间复杂度上可能有点问题。在每次函数调用中,您都要创建一个子数组(Arrays.copyOfRange(arr,m+1,arr.length)),它需要O(N)N表示从索引m+1到末尾的arr子数组。我认为这对O(logn)TC不起作用
public static int singleton(int[] arr) {
    int m = arr.length / 2;
    if (m == 0) return arr[0];
    if (m % 2 == 1) {
        if (arr[m] == arr[m-1]) return singleton(Arrays.copyOfRange(arr, m+1, arr.length));
        if (arr[m] != arr[m+1]) return arr[m];
        return singleton(Arrays.copyOfRange(arr, 0, m));
    }
    else {
        if (arr[m] == arr[m+1]) return singleton(Arrays.copyOfRange(arr, m+2, arr.length));
        if (arr[m] != arr[m-1]) return arr[m];
        return singleton(Arrays.copyOfRange(arr, 0, m+1));
    }
}      
    
public static void main(String args[])
{
    System.out.println(singleton(new int[]{ 1,1,2,2,4,5,5 }));
    System.out.println(singleton(new int[]{ 10,10,12,12,15,15,16,18,18 }));
    System.out.println(singleton(new int[]{1,2,2,5,5,6,6,7,7}));
    System.out.println(singleton(new int[]{1,1,2,5,5,6,6,7,7}));
    System.out.println(singleton(new int[]{10,10,12,12,15,15,16,16,18}));
}