【问题标题】:searching an unordered integer array搜索无序整数数组
【发布时间】:2013-03-01 16:08:21
【问题描述】:

搜索属于大型无序整数数组的整数元素的索引和值的最佳方法是什么?哪个是这个过程最好的搜索技术/算法?

int[] temp = new int[]{1,4,3,6,7,8,5,2,9,......}

现在说,我想搜索元素“9”,并且还需要获取该元素的索引。我的意思是,对数组元素进行排序并确定它在这里不起作用(因为我还需要跟踪元素的索引)。有什么建议?顺便说一句,我正在研究 java..

【问题讨论】:

  • 我认为您别无选择,因为您想保留索引。反复搜索。
  • 我可以使用散列并将元素的索引存储为值吗?
  • 在构建集合时对元素进行排序会不会令人望而却步?
  • 取决于您要实现/解决的问题。数组可能不是您任务中最好的数据结构。
  • 阵列有多大?它会改变吗?您需要多久进行一次搜索?

标签: java arrays search


【解决方案1】:

最少的编码是:

Arrays.asList(temp).indexOf(9)

【讨论】:

  • 我相信这会扫过列表两次。仅使用增强的 for 循环将是执行此操作的最佳方法。
  • 这个方案是不是类似于线性搜索过程?
  • 它会扫过列表两次?我想然后使用 for 循环进行线性搜索会更好。是的。
  • @Eashwar Cowls 的回答是最好的。如果您查看此代码的源代码,您会发现它在列表上迭代了两次,效率只有一半。
  • @Legend,为什么要谈效率? OP 没有具体说明他的任何要求。
【解决方案2】:

Begin at the beginning and go on till you come to the end: then stop.

刘易斯卡罗尔

当然,除非你在到达终点之前找到你要找的东西。

【讨论】:

    【解决方案3】:

    如果您手动执行此操作,您可以遍历每个数组项:

    public int indexOf(int search, int[] arr) {
    
        for(int i = 0; i < arr.length; i++) {
            if(arr[i] == search) {
                return i;
            }
        }
    
        return -1;
    
    }
    

    如果你知道数组在多次搜索之间不会改变,你也可以使用 Map 缓存结果。只要你改变数组时清空缓存。

    private Map<Integer, Integer> indexCache;
    
    public int indexOf(int search, int[] arr) {
    
        Integer cachedIndex = indexCache.get(search);
        if(cachedIndex != null) return cachedIndex;
    
        for(int i = 0; i < arr.length; i++) {
            if(arr[i] == search) {
                indexCache.put(search, i);
                return i;
            }
        }
    
        return -1;
    
    }
    

    实际上,您最好使用 Map 而不是完全使用数组来存储这些数据,因为它更适合键值查找。

    【讨论】:

    • 通过Java中的转换,最好在函数中将参数int[] arr放在int search之前。
    【解决方案4】:

    更好的方法是先对数组进行排序。

    Arrays.sort(array);
    Arrays.binarySearch(array, value);
    

    扫描一个未排序的数组需要线性时间“O(n)”。如果你不想对数组进行排序,你可以试试这个:

    public int find(int[] array, int value) {
            int index = -1;
            for (int i=0; i<array.length; i++) {
                if(array[i] == value) { index = i; }
            }
            return index;            
        }
    

    【讨论】:

    • 这是评论,不是回答。
    【解决方案5】:

    增强:

      int[] temp = new int[]{1,4,3,6,7,8,5,2,9,......}
        for (int i : temp) {
          if (i == 9)
            // do something
        }
    

    【讨论】:

      【解决方案6】:

      如果你需要多次搜索(同一个数组),你可能会创建一个临时结构,它结合了原始索引和值:

      class Pair implements Comparable<Pair> {
          final int index;
          final int value;
      
          Pair(int index, int value) {
              this.index = index;
              this.value = value;
          }
      
          public int compareTo(Pair oth) {
              if (value < oth.value) return -1;
              else if (value > oth.value) return 1;
              else if (index < oth.index) return -1;
              else if (index > oth.index) return 1;
              else return 0;
          }
      }
      
      final ArrayList<Pair> list = new ArrayList<Pair>();
      
      for (int k = 0; k < array.length; ++k) {
          list.add(new Pair(k, array[k]);
      }
      
      Arrays.sort(list);
      

      现在,list 按值排序,然后按索引排序。我们现在可以使用二分搜索(例如)来查找元素。但是请注意,这仅是值得的,如果您搜索值的次数(现在是 O(log n) 而不是 O(n))支配了构建数组所需的时间((O(n log n) 由于排序)。

      或者,您可以使用HashMapTreeMap 构建一个类似索引的结构,它将整数值映射到它在数组中的位置。在使用HashMap 的情况下,访问时间将在O(1) 左右,在TreeMap 的情况下,访问时间将是O(log n),与上面提出的二进制搜索方法一样。

      如果您必须经常搜索数组,所有这些建议显然是值得的。

      此外,您应该考虑,如果数组相当小,使用简单的线性搜索(如其他人所建议的那样)实际上可能是最快的解决方案,因为所涉及的“常量”和数组组件的良好局部性.

      因此,另一种方法是在将Pair 结构排序为两个整数数组(一个包含值,另一个包含索引)之后再次解包:

      int[] values = new int[list.size()];
      int[] indices = new int[list.size()];
      int pt = 0;
      
      for (Pair p: list) {
          values[pt] = p.value;
          indices[pt] = p.index;
          pt += 1;
      }
      

      现在您可以使用二进制搜索来搜索values 数组:

      int position = Arrays.binarySearch(values, valueToLookFor);
      if (position >= 0) {
      
          // Found it!
          int index = indices[position];
      
          System.out.println("Value was originally stored in " + index);
      
      } else {
      
          // Value not found
      }
      

      请记住:最简单的解决方案(线性扫描)可能是最快的,具体取决于数组的大小和您需要搜索条目的次数。我实际上会先尝试一下,并且只使用其中一个更复杂的建议,如果它被证明是一个瓶颈。

      【讨论】:

      • 感谢全面的解决方案,我终于用hashmap解决了我的问题!!
      猜你喜欢
      • 2011-04-13
      • 2018-08-09
      • 2018-03-26
      • 2012-01-04
      • 2015-04-16
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多