Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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
C 搜索元素的有效方法_C_Arrays_Algorithm_Sorting_Search - Fatal编程技术网

C 搜索元素的有效方法

C 搜索元素的有效方法,c,arrays,algorithm,sorting,search,C,Arrays,Algorithm,Sorting,Search,最近我接受了一次采访,他们问了我一个“搜索”问题。 问题是: 假设存在一个(正)整数数组,其中每个元素与其相邻元素相比是+1或-1 示例: array = [4,5,6,5,4,3,2,3,4,5,6,7,8]; 现在搜索7并返回其位置 我回答说: 将值存储在临时数组中,对其进行排序,然后应用二进制搜索 如果找到元素,则返回其在临时数组中的位置。 (如果数字出现两次,则返回其第一次出现) 但是,他们似乎对这个答案并不满意 正确答案是什么?您可以使用通常大于1的步长进行线性搜索。关键的观察结果是

最近我接受了一次采访,他们问了我一个“搜索”问题。
问题是:

假设存在一个(正)整数数组,其中每个元素与其相邻元素相比是
+1
-1

示例:

array = [4,5,6,5,4,3,2,3,4,5,6,7,8];
现在搜索
7
并返回其位置

我回答说:

将值存储在临时数组中,对其进行排序,然后应用二进制搜索

如果找到元素,则返回其在临时数组中的位置。
(如果数字出现两次,则返回其第一次出现)

但是,他们似乎对这个答案并不满意


正确答案是什么?

您可以使用通常大于1的步长进行线性搜索。关键的观察结果是,如果例如
数组[i]==4
而7还没有出现,那么7的下一个候选者位于索引
i+3
。使用一个while循环,该循环重复地直接到达下一个可行的候选对象

这里是一个实现,稍微概括一下。它查找数组中第一次出现的
k
(受+=1限制)或
-1
如果没有出现:

#include <stdio.h>
#include <stdlib.h>

int first_occurence(int k, int array[], int n);

int main(void){
    int a[] = {4,3,2,3,2,3,4,5,4,5,6,7,8,7,8};
    printf("7 first occurs at index %d\n",first_occurence(7,a,15));
    printf("but 9 first \"occurs\" at index %d\n",first_occurence(9,a,15));
    return 0;
}

int first_occurence(int k, int array[], int n){
    int i = 0;
    while(i < n){
        if(array[i] == k) return i;
        i += abs(k-array[i]);
    }
    return -1;
}

你的方法太复杂了。您不需要检查每个数组元素。第一个值是
4
,因此
7
至少是
7-4
元素,您可以跳过这些元素

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    int array[] = {4,5,6,5,4,3,2,3,4,5,6,7,8};
    int len = sizeof array / sizeof array[0];
    int i = 0;
    int steps = 0;
    while (i < len && array[i] != 7) {
        i += abs(7 - array[i]);
        steps++;
    }

    printf("Steps %d, index %d\n", steps, i);
    return 0;
}

编辑:在@Raphael Miedl和@Martin Zabel的评论之后有所改进。

传统线性搜索的一种变体可能是一种很好的方法。让我们选择一个元素,比如说
数组[i]=2
。现在,
array[i+1]
将是1或3(奇数),
array[i+2]
将是(仅限正整数)2或4(偶数)

这样继续下去,可以观察到一个模式-
数组[i+2*n]
将包含偶数,因此所有这些索引都可以忽略

而且我们可以看到,

array[i + 3] = 1 or 3 or 5
array[i + 5] = 1 or 3 or 5 or 7
因此,接下来应该检查索引
i+5
,根据在索引
i+5
中找到的值,可以使用while循环来确定下一个要检查的索引

虽然这具有复杂性
O(n)
(渐近复杂性方面的线性时间),但实际上它比普通线性搜索要好,因为所有索引都不访问


显然,如果数组[i](我们的起点)很奇怪,那么所有这些都会发生逆转。

约翰·科尔曼提出的方法很可能就是采访者所希望的。
如果您愿意进行更复杂的操作,可以增加预期的跳过长度:
调用目标值k。从位置p处第一个元素的值v开始,用绝对值av调用差值k-vdv。为了加快负搜索速度,请查看最后一个元素作为位置o处的另一个值u:如果dv×du为负,则存在k(如果k的任何出现都是可接受的,您可以像二进制搜索那样缩小索引范围)。如果av+au大于数组的长度,则不存在k。(如果dv×du为零,v或u等于k)
省略索引有效性:探测序列可能返回到v的(“下一个”)位置,其中k在中间:
o=p+2*av

如果dv×du为负,则从p+av到o-au求k(递归?)
如果为零,u等于k等于o。
如果DU等于DV,中间值不是K,或者AU超过AV,
或者从p+av到o-au找不到k,
p=o;dv=du;av=au并继续探测。

(对于60年代的全文,请使用Courier查看。我的“第一个想法”是使用
o=p+2*av-1
,这排除了du等于dv。)

步骤1

从第一个元素开始,检查它是否为7。假设
c
是当前位置的索引。因此,最初,
c=0

步骤2

如果是7,则找到索引。它是
c
。如果您已到达数组的末尾,请跳出

步骤3

如果不是,那么7必须至少是
|数组[c]-7 |
位置,因为每个索引只能添加一个单位。因此,将
| array[c]-7 |
添加到当前索引c中,然后再次转到步骤2进行检查


在最坏的情况下,当存在备用1和-1时,时间复杂度可能达到O(n),但平均情况会很快交付。

这里我给出了java中的实现

public static void main(String[] args) 
{       
    int arr[]={4,5,6,5,4,3,2,3,4,5,6,7,8};
    int pos=searchArray(arr,7);

    if(pos==-1)
        System.out.println("not found");
    else
        System.out.println("position="+pos);            
}

public static int searchArray(int[] array,int value)
{
    int i=0;
    int strtValue=0;
    int pos=-1;

    while(i<array.length)
    {
        strtValue=array[i];

        if(strtValue<value)
        {
            i+=value-strtValue;
        }
        else if (strtValue==value)
        {
            pos=i;
            break;
        }
        else
        {
            i=i+(strtValue-value);
        }       
    }

    return pos;
}
publicstaticvoidmain(字符串[]args)
{       
int arr[]={4,5,6,5,4,3,2,3,4,5,6,7,8};
int pos=搜索数组(arr,7);
如果(位置==-1)
System.out.println(“未找到”);
其他的
系统输出打印项次(“位置=”+pos);
}
公共静态int searchArray(int[]数组,int值)
{
int i=0;
int strtValue=0;
int pos=-1;

虽然(i<P>)是一种分而治之的风格解决方案,但我们可以跳过更多的元素,而不是从左向右扫描,在中间进行测试,在两个方向上跳过。
#include <stdio.h>                                                               
#include <math.h>                                                                

int could_contain(int k, int left, int right, int width);                        
int find(int k, int array[], int lower, int upper);   

int main(void){                                                                  
    int a[] = {4,3,2,3,2,3,4,5,4,5,6,7,8,7,8};                                   
    printf("7 first occurs at index %d\n",find(7,a,0,14));                       
    printf("but 9 first \"occurs\" at index %d\n",find(9,a,0,14));               
    return 0;                                                                    
}                                                                                

int could_contain(int k, int left, int right, int width){                        
  return (width >= 0) &&                                                         
         (left <= k && k <= right) ||                                            
         (right <= k && k <= left) ||                                            
         (abs(k - left) + abs(k - right) < width);                               
}                                                                                

int find(int k, int array[], int lower, int upper){                              
  //printf("%d\t%d\n", lower, upper);                                            

  if( !could_contain(k, array[lower], array[upper], upper - lower )) return -1;  

  int mid = (upper + lower) / 2;                                                 

  if(array[mid] == k) return mid;                                                

  lower = find(k, array, lower + abs(k - array[lower]), mid - abs(k - array[mid]));
  if(lower >= 0 ) return lower;                                                    

  upper = find(k, array, mid + abs(k - array[mid]), upper - abs(k - array[upper]));
  if(upper >= 0 ) return upper;                                                  

  return -1;                                                                     

}
#包括
#包括
int可以包含(int k,int left,int right,int width);
int find(int k,int数组[],int lower,int upper);
int main(void){
int a[]={4,3,2,3,2,3,4,5,4,5,6,7,8,7,8};
printf(“7首先出现在索引%d\n”,find(7,a,0,14));
printf(“但9优先”出现在“索引%d\n”,find(9,a,0,14));
返回0;
}                                                                                
int可以包含(int k,int left,int right,int width){
返回(宽度>=0)&
public static void main(String[] args) 
{       
    int arr[]={4,5,6,5,4,3,2,3,4,5,6,7,8};
    int pos=searchArray(arr,7);

    if(pos==-1)
        System.out.println("not found");
    else
        System.out.println("position="+pos);            
}

public static int searchArray(int[] array,int value)
{
    int i=0;
    int strtValue=0;
    int pos=-1;

    while(i<array.length)
    {
        strtValue=array[i];

        if(strtValue<value)
        {
            i+=value-strtValue;
        }
        else if (strtValue==value)
        {
            pos=i;
            break;
        }
        else
        {
            i=i+(strtValue-value);
        }       
    }

    return pos;
}
#include <stdio.h>                                                               
#include <math.h>                                                                

int could_contain(int k, int left, int right, int width);                        
int find(int k, int array[], int lower, int upper);   

int main(void){                                                                  
    int a[] = {4,3,2,3,2,3,4,5,4,5,6,7,8,7,8};                                   
    printf("7 first occurs at index %d\n",find(7,a,0,14));                       
    printf("but 9 first \"occurs\" at index %d\n",find(9,a,0,14));               
    return 0;                                                                    
}                                                                                

int could_contain(int k, int left, int right, int width){                        
  return (width >= 0) &&                                                         
         (left <= k && k <= right) ||                                            
         (right <= k && k <= left) ||                                            
         (abs(k - left) + abs(k - right) < width);                               
}                                                                                

int find(int k, int array[], int lower, int upper){                              
  //printf("%d\t%d\n", lower, upper);                                            

  if( !could_contain(k, array[lower], array[upper], upper - lower )) return -1;  

  int mid = (upper + lower) / 2;                                                 

  if(array[mid] == k) return mid;                                                

  lower = find(k, array, lower + abs(k - array[lower]), mid - abs(k - array[mid]));
  if(lower >= 0 ) return lower;                                                    

  upper = find(k, array, mid + abs(k - array[mid]), upper - abs(k - array[upper]));
  if(upper >= 0 ) return upper;                                                  

  return -1;                                                                     

}

const findMeAnElementsFunkyArray = (arr, ele, i) => {
  const elementAtCurrentIndex = arr[i];

  const differenceBetweenEleAndEleAtIndex = Math.abs(
    ele - elementAtCurrentIndex
  );

  const hop = i + differenceBetweenEleAndEleAtIndex;

  if (i >= arr.length) {
    return;
  }
  if (arr[i] === ele) {
    return i;
  }

  const result = findMeAnElementsFunkyArray(arr, ele, hop);

  return result;
};

const array = [4,5,6,5,4,3,2,3,4,5,6,7,8];

const answer = findMeAnElementsFunkyArray(array, 7, 0);

console.log(answer);