【问题标题】:Sorting and Comparing strings without using string library functions不使用字符串库函数对字符串进行排序和比较
【发布时间】:2017-01-29 15:35:04
【问题描述】:

挑战: 给定一个排序的名称数组(只有名字)和一个名称 X,我需要找出它在数组中出现的次数。约束:只允许二进制搜索。我也不能使用任何字符串库函数。 样本输入:

3
abc
abc
pqr
pqr

输出: 1(因为 pqr 在字符串/单词数组中只出现一次)。

【问题讨论】:

  • 酷挑战。祝你好运。
  • 你的代码在哪里?
  • 我投票决定将此问题作为题外话结束,因为它是一个家庭作业转储,没有显示出自己的努力。
  • 我能够通过线性搜索和使用字符串库函数来解决挑战。但是,我对施加约束的算法一无所知。
  • 那么祝你好运:)

标签: c algorithm sorting


【解决方案1】:

1) 不使用字符串库比较字符串:自己实现字符串比较功能:比较两个字符串的第一个字符,只有相等才比较下一个字符,以此类推。

2) 排序数组和二分查找:Binary search 非常适合排序数组。设 x 为查询字符串。

第 1 步:使用二分查找在排序后的数组中查找x。

第2步:如果找不到,返回0。

第三步:如果找到,在左右子数组中对x进行二分搜索。记录结果索引。

重复第3步(注意:每个循环中的左、右子数组较小),如果在左(或右)子数组中找不到x,则停止左(或右)方向的搜索。之前找到的 left 和 right 的索引给出了结果的范围。

【讨论】:

  • 不应该回答。 OP没有表现出他试图自己做的任何努力。不要用勺子喂食。此外,这个问题写得不好:他说他知道如何使用线性搜索来做到这一点,但这不是一个选择。在您的答案中,您结合了线性搜索和二进制搜索。我们不知道这样做是否可以。
  • 关于问题:如果你想知道相等元素的数量,最小比较次数是那些相等元素的数量。线性扫描整个数组不同于线性扫描只有相等的元素
  • 关于 OP:答案给出了想法,而不是代码。为了完成它,OP 仍然需要完成这项工作。我在这里看到了很多问题,OP 提出了类似的问题并给出了一些代码。然后人们跳进去给他完美的运行代码。在我看来,那是最糟糕的。但没有人说它不好。
  • 考虑到任务的奇怪性,如果目标是对 X 进行二分搜索,加 1 以计数并删除该字符串,我不会感到惊讶。重复直到 BS 找不到。无论如何,由于各种原因,不应回答此类问题。 @JJJ 的评论总结得很好
  • @Fureeish 对。仅使用 BS 更好。我更新了答案。
【解决方案2】:

关于如何比较 C 中的字符串,SO 上有 plenty 和 questions,所以我将指导您解决这些问题及其答案。基本上,解决方案是逐个字符地比较字符串,直到您找到一对不同的字符,或者直到您到达两个字符串的末尾。然后比较你到达的点的字符,并返回比较的结果。

至于使用二分查找来查找给定目标字符串在排序数组中出现的次数,可能最简单有效的解决方案是进行两次二分查找:一次查找起点,一次查找范围的终点数组元素等于目标。然后从起点到终点的距离将给出范围的长度。

以下二进制搜索例程将返回数组haystack 中小于目标needle 的最后一个元素的索引(或-1,如果没有这样的元素):

int find_last_less_than(int needle, int *haystack, int length) {
    int base = -1, step = length - base;

    // loop invariants:
    // 1. base == -1 || haystack[base] < needle
    // 2. base + step >= length || haystack[base + step] >= needle
    while (step > 1) {
        step = (step + 1) / 2;  // divide interval in half, rounding up
        int index = base + step;
        if (index < length && haystack[index] < needle) base += step;
    }
    return base;
}

请注意,为简单起见(并避免只是用勺子喂您整个解决方案),此代码搜索整数数组而不是字符串,但我相信您可以根据需要弄清楚如何修改它。

希望,还应该清楚如何修改搜索,以便找到最后一个元素小于的目标,而不是找到最后一个元素的索引小于或等于目标。从后者中减去前者将得出目标在数组中出现的次数。

【讨论】:

  • 我在您的评论中看到 find_last_less_than 为 variants of binary search。很高兴知道。我一直在想一个标准的 BS。
  • 我认为这是一个标准的二分搜索。通过变体,我的意思是扩展代码以在一次搜索中找到两个端点。在这种情况下,一个相当简单的优化是在函数中添加一个额外的变量int limit = length;,并在循环内添加一个额外的else if (index &lt; length &amp;&amp; haystack[index] &gt; needle) limit = index; 行。这样,在找到下限base 后,您只需搜索从base 到limit-1 的范围即可找到上限。
  • 我认为你的函数是指数搜索变体,就像 Wiki 中的定义一样,en.wikipedia.org/wiki/…
  • 我仍然会说这只是一个基本的二进制搜索。如果您更习惯于看到用left 和right 变量编写的二进制搜索,那么请在我的代码中将base 替换为left,并将step 替换为(right - left)。
  • 我现在看到了。是的,这是标准的BS。谢谢。
【解决方案3】:

这是我为执行任务而编写的代码:

enter code here
#include<stdio.h>
#include<stdlib.h>
int first(char *a[26],int low,int high,char *word,int n);
int last(char*a[26],int low,int high,char* word,int n);


int mycomp(char* a,char* b){

  int i = 0;
  while (a[i] == b[i] && a[i] != '\0')
   i++;
   if (a[i] > b[i])
      return 2;
   else if (a[i] < b[i])
     return -2;
   else
     return 0;



}

int main(){

int n,count=0;


scanf("%d",&n);
char dictionery[n][50];
char word[50];
  int i,j;
  for(i=0;i<n;i++)
      scanf("%s",dictionery[i]);

  scanf("%s",word);

 i = first(dictionery[n],0,n-1,word,n);

 if(i==-1)
  printf("No occurrances\n");

  else{
   j = last(dictionery[n],i,n-1,word,n);
   count = j-i+1;
   printf("%d\n",count);

  }

 return 0;
}

int first(char *a[26],int low,int high,char *word,int n){

 if(high >= low){
    int mid = (high+low)/2;
    int d = mycomp(word,a[mid-1]);
    int e = mycomp(word,a[mid]);
    if((mid==0 || d>0)&& e==0)
        return mid;

    else if(e>0)
       return first(*a[],mid+1,high,word,n);
    else
       return first(*a[],low,mid-1,word,n);




 }

 return -1;


}

int last(char* a[26],int low,int high,char* word,int n){

if(high>=low){
    int mid = (high+low)/2;
    int d = mycomp(word,a[mid+1]);
    int e = mycomp(word,a[mid]);

    if((mid==n-1 || d<0)&& e==0 )
       return mid;
    else if(e<0)
       return last(*a[],low,mid-1,word,n);
    else 
       return last(*a[],mid+1,high,word,n);

}
return -1;


}

这是执行任务的最有效方式吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多