查找 S(S=(min2∧min) 的最大可能值,其中 min2 和 min 是数组 k 元素中的最小和下一个最小整数



我正在研究一个编程问题。问题如下:

给定一个包含N个不同元素的数组A[]。令min2和min分别为区间[L,R]中最小和次小的元素,其中1≤L <R≤n>

S = (min2∧min)。

,其中∧为位异或算子。我必须找到s的最大值

我已经写了1个解,可以找到S的最大可能值,但是它的复杂度很高。我在想它是否可以优化。因为即使元素的范围k不是固定的,我必须计算所有范围,即k = 2到数组的长度。我使用的方法是首先取k为2从第0个元素开始,求最小值&前k个元素中的min2,计算S,如果它大于前一个S,就把它当作S,否则忽略它。之后,从第一个元素开始,我在接下来的k个元素中找到最小值&等等。其他更高的范围也一样,比如3,4,5…下面是我写的代码:

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
    int num = 0, S = Integer.MIN_VALUE, min = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
    int[] input = null;
    try {
        BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
        String s = bufferRead.readLine();
        num = Integer.parseInt(s);
        s = bufferRead.readLine();
        String arr[] = s.split(" ");
        input = new int[arr.length];
        for(int i =0; i<arr.length;i++) {
            input[i] = Integer.parseInt(arr[i]);
        }
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }

    for(int k=2;k<=input.length;k++) {
         int j =0;
         while(j<input.length-k+1)
             {
             int i=j;
             for(i=j;i<(j+k);i++)
             {
             if(input[i] < min)
                 {
                 min2 = min;
                 min = input[i];
             }
                 else if(input[i] > min && input[i] < min2)
                 {
                 min2 = input[i];
             }

         }
         int st = (((min2 & min)^(min2 | min)) & (min2 ^ min));

         if(st > S)
             S = st;
            j++;
            min = Integer.MAX_VALUE;
            min2 = Integer.MAX_VALUE;
         }
        }
        System.out.println( S );
    }
}

这个可以被优化吗?

这可以用线性时间O(N)空间算法来完成。

为了使事情更简单,在最小元素之后出现第二个最小元素的情况下这样做。然后将数组倒过来再做一次(或者只是从最后一个元素开始倒过来处理数组)。

使用数组的每个元素作为interval (A[R])的最右边的元素。现在唯一被认为是区间(A[L])最左边的元素是最近的小于A[R]的元素(如果有的话)。A[L]A[R]是这个区间中最小的两个元素,因此为它们计算S,并在必要时更新结果。并且最近的较小的元素可以使用堆栈找到。

伪代码:

result = -infinity
for each X in array A:
    while NOT stack.empty AND stack.top > X: stack.pop
    if NOT stack.empty:
        result = max(result, X XOR stack.top)
    stack.push(X)
reverse array A and repeat

证明:这个算法(确切地说,它的前半部分)尝试数组的每个元素作为某个区间的第二最小元素,使得(第一)最小元素在它的左边。显然,这里考虑了区间A[L]..A[R]。同样,如果我们将这个区间扩展到任意一边(或两边),并且这个扩展区间的所有附加元素都大于A[R],那么A[R]仍然是第二个最小的元素,并且该区间也被算法考虑(但它不会改变S的最优值)。如果至少有一个额外的元素小于A[R],或者我们不再扩展,而是开始缩小间隔,A[R]不再是第二个最小的元素,所以在这个特定的迭代中不考虑这样的间隔(但是当我们尝试其他元素作为第二个最大的元素或当我们期望当前元素右边的第一个最大的元素时考虑)。

最新更新