Java 在数组中查找数字

Java 在数组中查找数字,java,arrays,algorithm,Java,Arrays,Algorithm,以下问题是否有一个具有O(n)效率的解决方案 您需要在数组中找到一个单元格,使它前面的所有数字都小于它,后面的所有数字都大于它。您应该忽略第一个和最后一个单元格 例如,考虑以下列表: 1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11 在这种情况下,答案将是索引5处的数字7是的,当然可以在O(n)时间内完成。接下来有两种方法 第一种方法对于查找所有候选单元更为有用。对每个单元格设置两个额外的数据项进行一次O(n)传递,因此O(n)space(用空间换取时间可以解决大量优化问题)

以下问题是否有一个具有O(n)效率的解决方案

您需要在数组中找到一个单元格,使它前面的所有数字都小于它,后面的所有数字都大于它。您应该忽略第一个和最后一个单元格

例如,考虑以下列表:

1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11
在这种情况下,答案将是索引
5
处的数字
7

是的,当然可以在
O(n)
时间内完成。接下来有两种方法

第一种方法对于查找所有候选单元更为有用。对每个单元格设置两个额外的数据项进行一次
O(n)
传递,因此
O(n)
space(用空间换取时间可以解决大量优化问题)

您需要为每个单元格计算的两项是左侧的最大值和右侧的最小值。第一个过程为所有单元格设置这些项,但末尾没有意义的单元格除外(显然是伪代码):

值相对于其上下两个值排序的唯一候选单元格是标有
^
7


现在请记住,这是一个相对容易理解的解决方案,可以找到多个满足约束的项。考虑到您只需要一个项目,就有可能获得更好的性能(尽管仍然是O(n))

基本思想是从左向右遍历数组,对于每个单元格,检查左侧的所有内容是否较低,右侧的所有内容是否较高

第一点很简单,因为通过从左向右遍历,您可以记住遇到的最高值。第二点似乎涉及以某种方式展望未来,但有一个技巧可以用来避免这种“暂时的体操”

其思想是保持当前单元格左侧的最高值和当前答案的索引(最初设置为sentinel值)

如果当前答案是sentinel值,则选择满足“大于左侧所有值”的第一个单元格作为可能答案

而且,只要情况仍然如此,那就是你选择的细胞。但是,一旦您在其右侧找到一个小于或等于它的值,它就不再有效,因此您将放弃它并重新开始搜索

此搜索从当前点开始,而不是从一开始就开始,因为:

  • 当前答案之前但不包括此(较小或相等)单元格的所有内容都高于当前答案,否则您将已经找到较小或相等的单元格;及
  • 因此,该单元格必须小于或等于该范围内的每个单元格,因为它小于或等于当前答案;所以
  • 该范围内没有有效的单元格,它们都大于或等于此单元格
处理完非最终项后,您的答案将是sentinel或几乎满足约束的单元格

我之所以说“几乎”,是因为需要进行一次最终检查以确保最终项大于它,因为作为遍历的一部分,您没有对该项执行任何检查

因此,该beast的伪代码类似于:

# Store max on left and start with sentinel.

maxToLeft = cell[0]
answer = -1

for checking = 1 to cell.lastIndex-1 inclusive:
    switch on answer:
        # Save if currently sentinel and item valid.
        case -1:
            if cell[checking] > maxToLeft:
                answer = checking

        # Set back to sentinel if saved answer is now invalid.
        otherwise:
            if cell[answer] >= cell[checking]:
                answer = -1

    # Ensure we have updated max on left.

    if cell[checking] > maxToLeft:
        maxToLeft = cell[checking]

# Final check against last cell.

if answer != -1:
    if cell[cell.lastIndex] <= cell[answer]:
        answer = -1

创建一个附加阵列,该阵列通过在源阵列上从左向右进行计算。对于此数组中的任何索引N,该值是第一个数组中0:N-1之间观察到的最高值

int arr1 = new int[source.length];
int highest = MIN_INT;
for (int i = 0; i < source.length; i++) {
    arr1[i] = highest;
    if (source[i] > highest) {
        highest = source[i];
    }
}
现在,您只需将所有三个数组一起扫描,直到找到符合此条件的索引:

arr1[i] < source[i] < arr2[i] 

where:
     0 < i < (source.length-1)
arr1[i]
代码:

for(int i=1;i<(source.length-1);i++){
if((arr1[i]
这是O(N)时间。

对于时间和空间复杂性以及单个数组过程,这都有O(N)

逻辑:

// int[] arr = { 10, 11, 1, 2, 12, 13, 14};
int[] arr = {  1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11};
Integer firstMax = null;
Integer overallMax = null;

for (int i = 1; i < arr.length - 1; i++) {
    int currentElement = arr[i];
    if (firstMax == null) {
        if (overallMax == null) {
            firstMax = currentElement;
        } else if (overallMax != null && currentElement > overallMax) {
            firstMax = currentElement;
        }
    }
    if (overallMax == null || currentElement > overallMax) {
        overallMax = currentElement;
    }
    if (firstMax != null && currentElement < firstMax) {
        // We found a smaller element, so all max found so far is useless. Start fresh.
        firstMax = null;
    }
}

System.out.println(firstMax);
  • 找到迄今为止找到的第一个最大值和总最大值,继续遍历数组,直到找到小于第一个最大值的值
  • 如果您这样做了,那么将first_max和所有元素保留在此之前,因为所有这些元素都比我当前找到的元素多
  • 现在选择第一个最大值,这样下一个值应该大于我们一直在寻找的总最大值
  • 代码:

    // int[] arr = { 10, 11, 1, 2, 12, 13, 14};
    int[] arr = {  1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11};
    Integer firstMax = null;
    Integer overallMax = null;
    
    for (int i = 1; i < arr.length - 1; i++) {
        int currentElement = arr[i];
        if (firstMax == null) {
            if (overallMax == null) {
                firstMax = currentElement;
            } else if (overallMax != null && currentElement > overallMax) {
                firstMax = currentElement;
            }
        }
        if (overallMax == null || currentElement > overallMax) {
            overallMax = currentElement;
        }
        if (firstMax != null && currentElement < firstMax) {
            // We found a smaller element, so all max found so far is useless. Start fresh.
            firstMax = null;
        }
    }
    
    System.out.println(firstMax);
    
    //int[]arr={10,11,1,2,12,13,14};
    int[]arr={1,3,2,6,5,7,9,8,10,8,11};
    整数firstMax=null;
    整数overallMax=null;
    对于(int i=1;ioverallMax){
    firstMax=currentElement;
    }
    }
    if(overallMax==null | | currentElement>overallMax){
    总最大值=当前元素;
    }
    if(firstMax!=null&¤tElement
    PS:根据我的分析,我觉得这应该足够了,并且适用于所有情况。不确定是否遗漏了任何案例。

    这里有一个O(n),Python中的一次解决方案。Java的端口很简单:

    随机导入
    A=[random.randint(1,10)表示范围(0,5)中的i]#生成大小为5的列表。
    max_seen=A[0]
    候选人=无
    对于范围(1,len(A))中的i:
    如果候选人没有:
    如果[i]>max_出现:
    候选人=i
    其他:
    如果A[i]A[0..x-1]A[x]>max(A[0..x-1])。因此,我们保持到目前为止看到的最大值,找到满足条件1的第一个x,并遍历数组,验证条件2是否满足。如果条件2从未得到验证,我们知道下一个可能的候选对象
    
    cell = [1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11]
    maxToLeft = cell[0]
    answer = -1
    for checking in range(1, len(cell) - 1):
        if answer == -1:
            if cell[checking] > maxToLeft:
                answer = checking
        else:
            if cell[answer] >=cell[checking]:
                answer = -1
        if cell[checking] > maxToLeft:
            maxToLeft = cell[checking]
    
    if answer != -1:
        if cell[len(cell] - 1] <= cell[answer]:
            answer = -1
    
    if answer == -1:
        print ("Not found")
    else:
        print("Found value", cell[answer], "at index", answer);
    
    
    print(highLeft)
    print(cell)
    print(lowRight)
    
    for idx in range(1, len(cell) - 1):
        if cell[idx] > highLeft[idx] and cell[idx] < lowRight[idx]:
            print("Found value", cell[idx], "at index", idx)
    
    [0, 1, 3, 3, 6, 6, 7, 9, 9, 10, 10]
    [1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11]
    [2, 2, 5, 5, 7, 8, 8, 8, 8, 11, 0]
    Found value 7 at index 5
    
    int arr1 = new int[source.length];
    int highest = MIN_INT;
    for (int i = 0; i < source.length; i++) {
        arr1[i] = highest;
        if (source[i] > highest) {
            highest = source[i];
        }
    }
    
    arr2 = new int[source.length];
    int lowest = MAX_INT;
    for (int i = (source.length-1); i <= 0; i--) {
        arr2[i] = lowest;
        if (source[i] < lowest) {
            lowest = source[i];
        }
    }
    
    source: 1   3   2   6   5  7   9   8   10   8   11
    arr1:   MIN 1   3   3   6  6   7   9    9  10   10
    arr2:   2   2   5   5   7  8   8   8    8  11   MAX
    
    arr1[i] < source[i] < arr2[i] 
    
    where:
         0 < i < (source.length-1)
    
    for (int i = 1; i < (source.length-1); i++) {
        if ((arr1[i] < source[i]) && (source[i] < arr2[i])) {
            return i; // or return source[i]
        }
    }
    
    // int[] arr = { 10, 11, 1, 2, 12, 13, 14};
    int[] arr = {  1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11};
    Integer firstMax = null;
    Integer overallMax = null;
    
    for (int i = 1; i < arr.length - 1; i++) {
        int currentElement = arr[i];
        if (firstMax == null) {
            if (overallMax == null) {
                firstMax = currentElement;
            } else if (overallMax != null && currentElement > overallMax) {
                firstMax = currentElement;
            }
        }
        if (overallMax == null || currentElement > overallMax) {
            overallMax = currentElement;
        }
        if (firstMax != null && currentElement < firstMax) {
            // We found a smaller element, so all max found so far is useless. Start fresh.
            firstMax = null;
        }
    }
    
    System.out.println(firstMax);
    
    /**
     * Problem:
     *  there is an array of number, find an element which is larer than elements before it, and smaller than elements after it,
     *  refer:  http://stackoverflow.com/questions/41293848
     * 
     * Solution:
     *  loop through array, remember max value of previous loopped elements, compare it to next element, to check whether the first condition is met,
     *  when found an element met the first condition, then loop elements after it to see whether second condition is met,
     *  if found, then that's it; if not found, say at position 'y' the condition is broken, then the next candidate must be after y, thus resume the loop from element after y,
     *  until found one or end of array,
     * 
     * @author Eric Wang
     * @date 2016-12-23 17:08
     */
    #include <stdio.h>
    
    // find first matched number, return its index on found, or -1 if not found,
    extern int findFirstMidNum(int *arr, int len);
    
    int findFirstMidNum(int *arr, int len) {
        int i=0, j;
        int max=arr[0];
    
        while(i < len) {
            printf("\n");
            if(arr[i] <= max) {
                printf("give up [%d]-th element {%d}, 1st condition not met\n", i, arr[i]);
                i++;
                continue;
            }
            max = arr[i]; // update max,
    
            printf("checking [%d]-th element {%d}, for 2nd condition\n", i, arr[i]);
            j = i+1;
            while(j < len) {
                if(arr[j] <= max) {
                    printf("give up [%d]-th element {%d}, 2nd condition not met\n", i, arr[i]);
                    break;
                }
                j++;
            }
            printf("position after 2nd check:\ti = %d, j = %d\n", i, j);
    
            if(j==len && j>i+1) {
                return i;
            } else {
                max = arr[j-1]; // adjust max before jump,
                i = j+1; // jump
                printf("position adjust to [%d], max adjust to value {%d}, after 2nd check\n", i, arr[j-1]);
            }
        }
    
        return -1;
    }
    
    int main() {
        int arr[] = {1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11};
        int len = sizeof(arr)/sizeof(arr[0]);
        printf("\n============ Input array ============\n");
        printf("size:\t%d\n", len);
        printf("elements:\t{");
    
        int i;
        for(i=0; i<len; i++) {
            printf("%d, ", arr[i]);
        }
        printf("}\n\n");
    
        printf("\n============ Running info ============\n");
        int pos = findFirstMidNum(arr, len);
    
        printf("\n============ Final result============\n");
        if (pos < 0) {
            printf("Element not found.\n");
        } else {
            printf("Element found at:\n\t position [%d], with value: {%d}\n", pos, arr[pos]);
        }
        printf("\n");
    
        return 0;
    }
    
    ============ Input array ============
    size:   11
    elements:   {1, 3, 2, 6, 5, 7, 9, 8, 10, 8, 11, }
    
    
    ============ Running info ============
    
    give up [0]-th element {1}, 1st condition not met
    
    checking [1]-th element {3}, for 2nd condition
    give up [1]-th element {3}, 2nd condition not met
    position after 2nd check:   i = 1, j = 2
    position adjust to [3], max adjust to value {3}, after 2nd check
    
    checking [3]-th element {6}, for 2nd condition
    give up [3]-th element {6}, 2nd condition not met
    position after 2nd check:   i = 3, j = 4
    position adjust to [5], max adjust to value {6}, after 2nd check
    
    checking [5]-th element {7}, for 2nd condition
    position after 2nd check:   i = 5, j = 11
    
    ============ Final result============
    Element found at:
         position [5], with value: {7}