Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
Algorithm 查找不在列表中的最小非负整数的算法_Algorithm_Sorting_Integer - Fatal编程技术网

Algorithm 查找不在列表中的最小非负整数的算法

Algorithm 查找不在列表中的最小非负整数的算法,algorithm,sorting,integer,Algorithm,Sorting,Integer,给定一个整数列表,如何最好地找到不在列表中的整数 列表可能非常大,整数可能很大(即大整数,而不仅仅是32位整数) 如果有什么不同,列表是“可能”排序的,即99%的时间会被排序,但我不能依赖总是被排序 编辑- 为了澄清,鉴于列表{0,1,3,4,7},可接受解决方案的示例为-2,2,8和10012,但我更愿意找到最小的非负解决方案(即2)如果有一种算法可以找到它,而不需要对整个列表进行排序。除非对其进行排序,否则必须逐项进行线性搜索,直到找到匹配项或到达列表的末尾。如果您可以保证它是排序的,那么您

给定一个整数列表,如何最好地找到不在列表中的整数

列表可能非常大,整数可能很大(即大整数,而不仅仅是32位整数)

如果有什么不同,列表是“可能”排序的,即99%的时间会被排序,但我不能依赖总是被排序

编辑-


为了澄清,鉴于列表{0,1,3,4,7},可接受解决方案的示例为-2,2,8和10012,但我更愿意找到最小的非负解决方案(即2)如果有一种算法可以找到它,而不需要对整个列表进行排序。

除非对其进行排序,否则必须逐项进行线性搜索,直到找到匹配项或到达列表的末尾。如果您可以保证它是排序的,那么您可以始终使用BinarySearch的数组方法,或者直接使用您自己的二进制搜索


或者像Jason提到的,总是可以选择使用哈希表。

一个简单的方法是迭代列表以获得最高值
n
,然后您知道
n+1
不在列表中

编辑:

找到最小未使用正数的方法是从零开始,扫描列表中的该数字,重新开始,如果找到该数字,则增加。为了提高效率,并利用列表被排序的高概率,可以将小于当前值的数字移动到列表中未使用的部分

此方法使用列表开头作为较低数字的存储空间,
startIndex
变量跟踪相关数字的起始位置:

public static int GetSmallest(int[] items) {
    int startIndex = 0;
    int result = 0;
    int i = 0;
    while (i < items.Length) {
        if (items[i] == result) {
            result++;
            i = startIndex;
        } else {
            if (items[i] < result) {
                if (i != startIndex) {
                    int temp = items[startIndex];
                    items[startIndex] = items[i];
                    items[i] = temp;
                }
                startIndex++;
            }
            i++;
        }
    }
    return result;
}
publicstaticintgetminimable(int[]项){
int startIndex=0;
int结果=0;
int i=0;
while(i
我做了一个性能测试,在那里我创建了10万个从0到19999的随机数的列表,这使得平均最低数在150左右。在测试运行中(每个测试列表有1000个),该方法在未排序列表中发现的最小数量平均为8.2毫秒,在排序列表中发现的最小数量平均为0.32毫秒


(我没有检查该方法离开列表的状态,因为它可能会交换列表中的某些项。它离开的列表至少包含相同的项,并且当它向下移动较小的值时,我认为它实际上应该在每次搜索时变得更排序。)

除非您100%确定它已排序,最快的算法仍然必须至少查看列表中的每个数字一次,以至少验证列表中没有数字。

“可能已排序”意味着您必须将其视为完全未排序。当然,如果你能保证它被分类,这很简单。只需查看第一个或最后一个元素并加或减1。

理论上,找到最大值并加1。假设受BigInteger类型的最大值约束,如果未排序,则对列表进行排序,并查找间隙。

如果数字没有任何限制,则可以执行线性搜索以查找列表中的最大值,并返回大一的数字

如果数字确实有限制(例如,max+1和min-1可能会溢出),则可以使用排序算法。然后浏览列表,找到第一对不连续的数字v_i和v_{i+1}。返回v_i+1

要获得最小的非负整数(基于问题中的编辑),您可以:

  • 使用如上所述的部分排序对列表进行排序。二进制搜索列表中的0。从该值遍历列表,直到找到两个数字之间的“间隙”。如果到达列表的末尾,请返回最后一个值+1

  • 将值插入哈希表。然后从0向上迭代,直到找到不在列表中的整数

    • 您是否正在寻找一个(因为您说输入任意大)?如果是这样,请看一看


      否则,如前所述,对布尔集合的输入、搜索和打开/关闭元素进行散列(将散列索引放入集合中)。

      有几种方法:

      • 找到列表中最大的整数并将其存储在x中。x+1将不在列表中。这同样适用于使用min()和x-1

      • 当N是列表的大小时,分配一个大小为
        (N+31)/32
        的int数组。对于列表中的每个元素,在数组索引i/32处设置整数的位
        v&31
        (其中
        v
        是元素的值)。忽略
        i/32>=array.length
        的值。现在搜索第一个数组项,即“!=0xFFFFFF'(用于32位整数)


      如果你不能保证它是被排序的,那么你有一个最佳的时间效率O(N),因为你必须查看每个元素,以确保你的最终选择不在那里。因此,问题是:

    • 可以在O(N)内完成吗
    • 什么是最佳空间效率
    • Chris Doggett的查找最大值并添加1的解决方案是O(N)和空间效率(O(1)内存使用)


      如果你只想要最好的答案,那么这是一个不同的问题。

      假设这就是我正在思考的问题:

      1
      n
      范围内,您有一个
      集合
      所有
      整数
      ,但其中一个
      整数
      丢失。告诉我缺少
      int
      中的哪一个

      这是一个很容易用一些简单的数学知识来解决的问题。众所周知
          public int solution(int[] A) {
          if (A != null && A.length > 0) {
              quickSort(A, 0, A.length - 1);
          }
      
          int result = 1;
          if (A.length == 1 && A[0] < 0) {
              return result;
          }
      
          for (int i = 0; i < A.length; i++) {
              if (A[i] <= 0) {
                  continue;
              }
              if (A[i] == result) {
                  result++;
              } else if (A[i] < result) {
                  continue;
              } else if (A[i] > result) {
                  return result;
              }
          }
      
          return result;
      }
      
      private void quickSort(int[] numbers, int low, int high) {
          int i = low, j = high;
          int pivot = numbers[low + (high - low) / 2];
      
          while (i <= j) {
              while (numbers[i] < pivot) {
                  i++;
              }
              while (numbers[j] > pivot) {
                  j--;
              }
      
              if (i <= j) {
                  exchange(numbers, i, j);
                  i++;
                  j--;
              }
          }
          // Recursion
          if (low < j)
              quickSort(numbers, low, j);
          if (i < high)
              quickSort(numbers, i, high);
      }
      
      private void exchange(int[] numbers, int i, int j) {
          int temp = numbers[i];
          numbers[i] = numbers[j];
          numbers[j] = temp;
      }
      
      using System.Collections.Generic;
      using System.Linq;
      
      class Solution {
      
          public int solution(int[] A) {
              if (A == null) {
                  return 1;
              } else {
                  if (A.Length == 0) {
                      return 1;
                  }
              }
              List<int> list_test = new List<int>(A);
              list_test = list_test.Distinct().ToList();
              list_test = list_test.Where(i => i > 0).ToList();
              list_test.Sort();
              if (list_test.Count == 0) {
                  return 1;
              }
              int lastValue = list_test[list_test.Count - 1];
              if (lastValue <= 0) {
                  return 1;
              }
              int firstValue = list_test[0];
              if (firstValue > 1) {
                  return 1;
              }
              return BinarySearchList(list_test);
          }
      
          int BinarySearchList(List<int> list) {
              int returnable = 0;
              int tempIndex;
              int[] boundaries = new int[2] { 0, list.Count - 1 };
              int testCounter = 0;
              while (returnable == 0 && testCounter < 2000) {
                  tempIndex = (boundaries[0] + boundaries[1]) / 2;
                  if (tempIndex != boundaries[0]) {
                      if (list[tempIndex] > tempIndex + 1) {
                          boundaries[1] = tempIndex;
                      } else {
                          boundaries[0] = tempIndex;
                      }
                  } else {
                      if (list[tempIndex] > tempIndex + 1) {
                          returnable = tempIndex + 1;
                      } else {
                          returnable = tempIndex + 2;
                      }
                  }
                  testCounter++;
              }
              if (returnable == list[list.Count - 1]) {
                  returnable++;
              }
              return returnable;
          }
      
      }