Java 如何制作';双环路(O(n^2))和#x27;进入';单for循环(O(n))和#x27;?

Java 如何制作';双环路(O(n^2))和#x27;进入';单for循环(O(n))和#x27;?,java,performance,Java,Performance,我正在研究算法,我正在努力使它更高效、更干净 这是一种算法,用于查找不重复的值并返回其中的第一个值 下面是我的代码 // example input of array. int[] A = [2, 5, 1, 5, 1, 3, 9, 2]; // check pairs. And make them -1 // from 0 index to last index. for(int i = 0 ; i < A.length ; i++){ // from the next ind

我正在研究算法,我正在努力使它更高效、更干净

这是一种算法,用于查找不重复的值并返回其中的第一个值

下面是我的代码

// example input of array.
int[] A = [2, 5, 1, 5, 1, 3, 9, 2];

// check pairs. And make them -1
// from 0 index to last index.
for(int i = 0 ; i < A.length ; i++){
    // from the next index to the last index ( the rest indices ).
    for(int j=i+1; j < A.length ; j++){
        // if ith value and jth value are euqal and never checked make them -1 so that you can mark they have been visited.
        if(A[i]==A[j] && A[i]>0){
            A[i]=-1; A[j]=-1; 
        }
    }
}

// find the first number among the left positive values.
for(int i = 0 ; i < A.length ; i++){
    if(A[i]>0) return A[i];
}
// if there is no positive value, return 0;
return 0;
//数组的示例输入。
int[]A=[2,5,1,5,1,3,9,2];
//配对检查。并使它们成为-1
//从0索引到最后一个索引。
for(int i=0;i0){
A[i]=-1;A[j]=-1;
}
}
}
//在左正值中找到第一个数字。
for(int i=0;i0)返回A[i];
}
//如果没有正值,则返回0;
返回0;

如你所见,这是O(n^2)。我正在努力使它更快或看起来更干净。我想我可以把它设为O(n),这意味着只使用一个for循环(而不是double for循环)。你认为有可能吗?

你想返回第一个元素不重复还是有?因为如果你不必是第一个,你可以用O(nLGn)来做。使用某种需要对数时间的方法对数组进行排序,例如mergesort,然后通过查找一个位置与下一个/上一个位置不相同来遍历数组

要返回第一个元素不重复还是有?因为如果你不必是第一个,你可以用O(nLGn)来做。使用某种需要对数时间的方法对数组进行排序,例如mergesort,然后通过查找一个位置来遍历它,该位置与下一个/上一个位置不同

您可以使用整数排序的思想。它有三个循环,但它们不是嵌套的。它可以处理负数。时间复杂度是
O(n+m)
,其中
n
是数组的长度,
m
是数组中最大值和最小值之间的差值

下面是一个工作的java示例:

public class findDup {
    public static void main(String[] args) {
        int arr[] = { -4, -6, -4, 8, 9, 8, 9, 10, -3 };
        printNonDups(arr);
    }

    public static void printNonDups(int arr[]) {
    // Find max and min.                                                                                                                                                                                       

        int max=arr[0];
        int min=arr[0];

        // Find max and min. 
        // O(arr.length)
        for(int i=0; i<arr.length; i++) {
            if(arr[i]>max)
                max=arr[i];
            if(arr[i]<min)
                min=arr[i];
        }

        int tmp[] = new int[max-min+1];

        // Count the number of occurrences of each number.
        // O(arr.length) 
        for(int i=0; i<arr.length; i++) 
            tmp[arr[i]-min]++;

        // Print all unique values
        // O(max-min)
        for(int i=0; i<tmp.length; i++) 
            if(tmp[i]==1) {
                System.out.println(i+min);
                // break; // Uncomment to stop after first non-duplicate                                                                                                                                               
            }
    }
}
公共类查找{
公共静态void main(字符串[]args){
int arr[]={-4,-6,-4,8,9,8,9,10,-3};
打印件(arr);
}
公共静态无效打印文件(int arr[]{
//找到最大值和最小值。
int max=arr[0];
int min=arr[0];
//找到最大值和最小值。
//O(平均长度)
对于(int i=0;imax)
max=arr[i];

if(arr[i]您可以使用整数排序的思想。它是三个循环,但它们不是嵌套的。它可以处理负数。时间复杂度是
O(n+m)
,其中
n
是数组的长度,
m
是数组中最大值和最小值之间的差

下面是一个工作的java示例:

public class findDup {
    public static void main(String[] args) {
        int arr[] = { -4, -6, -4, 8, 9, 8, 9, 10, -3 };
        printNonDups(arr);
    }

    public static void printNonDups(int arr[]) {
    // Find max and min.                                                                                                                                                                                       

        int max=arr[0];
        int min=arr[0];

        // Find max and min. 
        // O(arr.length)
        for(int i=0; i<arr.length; i++) {
            if(arr[i]>max)
                max=arr[i];
            if(arr[i]<min)
                min=arr[i];
        }

        int tmp[] = new int[max-min+1];

        // Count the number of occurrences of each number.
        // O(arr.length) 
        for(int i=0; i<arr.length; i++) 
            tmp[arr[i]-min]++;

        // Print all unique values
        // O(max-min)
        for(int i=0; i<tmp.length; i++) 
            if(tmp[i]==1) {
                System.out.println(i+min);
                // break; // Uncomment to stop after first non-duplicate                                                                                                                                               
            }
    }
}
公共类查找{
公共静态void main(字符串[]args){
int arr[]={-4,-6,-4,8,9,8,9,10,-3};
打印件(arr);
}
公共静态无效打印文件(int arr[]{
//找到最大值和最小值。
int max=arr[0];
int min=arr[0];
//找到最大值和最小值。
//O(平均长度)
对于(int i=0;imax)
max=arr[i];

如果(arr[i]那么根据我的理解,如果没有返回0,您希望返回第一个既不是0也不是在下一个位置重复的值

那么:

for( int i=0; i<A.length-1;i++)
{ 
    if( A[i]>0 && A[i]!=A[i+1] ) return A[i];
}
return 0;
for(int i=0;i0&&A[i]!=A[i+1])返回A[i];
}
返回0;

当然,如果您还需要修改数组,因为您将继续使用它,您将需要进一步的逻辑。

因此,据我所知,如果没有返回0,您希望返回第一个既不为0也不在下一位置重复的值

那么:

for( int i=0; i<A.length-1;i++)
{ 
    if( A[i]>0 && A[i]!=A[i+1] ) return A[i];
}
return 0;
for(int i=0;i0&&A[i]!=A[i+1])返回A[i];
}
返回0;

当然,如果您还需要修改数组,因为您将继续使用它,那么您将需要进一步的逻辑。

如@gabi13的回答中所述,可能最简单和最有效的方法是使用O(nlogn)排序算法,然后遍历数组搜索第一个元素,该元素不等于下一个(或上一个)元素

不过,我想进一步澄清一下,因为您的问题中似乎混淆了复杂性概念

将两个循环减少为一个不会将O(n²)转换为O(n),除非它们是嵌套的(但您需要一种方法来丢弃最后一个循环,而不是嵌套的一个)

第一个循环是导致O(n²)的循环,因为它有两个嵌套循环遍历数组。即使删除最后一个循环,代码也将保持O(n²)

尽管您的方法不能转化为O(n)(关于替代方法O(nlogn),请参见@gabe13的答案),但您的实现是可以优化的


首先,如果你只需要关注正值,如果[i]0,如果你没有找到一个重复(即嵌套循环结束时没有找到一个对),你就不需要检查对。在这种情况下,你已经有了你的解决方案。

正如@gabi13的答案中所述,最简单和最有效的方法可能是使用O(nlogn)排序算法,然后遍历数组搜索不等于下一个(或上一个)的第一个元素

不过,我想进一步澄清一下,因为您的问题中似乎混淆了复杂性概念

将两个循环减少为一个不会将O(n²)转换为O(n),除非它们是嵌套的(但您需要一种方法来丢弃最后一个循环,而不是嵌套的一个)