zoukankan      html  css  js  c++  java
  • 10.6 随笔,木有主题

    (1) 
    一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
    请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
    注意:
    - 5个数值允许是乱序的。比如: 8 7 5 0 6
    - 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
    - 0可以多次出现。
    - 复杂度如果是O(n2)则不得分。

    (2)
    设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
    复杂度如果是O(n2)则不得分。

    (3)
    一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。
    复杂度如果是O(n2)则不得分。

    (4)
    一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
    复杂度最好是O(n),如果是O(n2)则不得分。

    (5)链表和数组的区别,内存中的连续情况   插入删除的效率   

    (6) 编写实现链表排序的算法,为什么选择这种方法

      

            当我们需要对链表进行排序时,由于不能对它的元素进行随机访问,所以更适合使用归并排序,大名鼎鼎的快速排序用到链表上,效率也很低,原因还是在于不能对链表中的元素进行随机访问,同理,采用堆排序更是不可能的事情。

            算法具体实现时需要一个指向头节点(链表的第一个节点,链表中不包含额外的一个节点来作头节点)的指针,这是因为在算法实现的时候,不大可能第一个节点正 好就是所有元素中最小的一个,则链表的头节点会改变,因此我们需要一个指向头节点的指针来存储不断变化的头节点。

    算法思想:

    MergeSort(headRef)
    1) If head is NULL or there is only one element in the Linked List
        then return.
    2) Else divide the linked list into two halves.
          FrontBackSplit(head, &a, &b); /* a and b are two halves */
    3) Sort the two halves a and b.
          MergeSort(a);
          MergeSort(b);
    4) Merge the sorted a and b (using SortedMerge() discussed here)
       and update the head pointer using headRef.
         *headRef = SortedMerge(a, b);
    代码示例:
    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3.   
    4. /*Link list node*/  
    5. struct node  
    6. {  
    7.     int data;  
    8.     struct node* next;  
    9. };  
    10.   
    11. /*function prototype */  
    12. struct node* SortedMerge(struct node* a, struct node* b);  
    13. void FrontBackSplit(struct node* source, struct node** frontRef, struct node** backRef);  
    14.   
    15. /*sorts the linked list by changing next pointers(not data) */  
    16. void MergeSort(struct node** headRef)  
    17. {  
    18.     struct node* head = *headRef;  
    19.     struct node* a;  
    20.     struct node* b;  
    21.   
    22.     /*base case-- length 0 or 1 */  
    23.     if((head == NULL) || (head->next == NULL))  
    24.     {  
    25.         return;  
    26.     }  
    27.       
    28.     /*Split head into 'a' and 'b' sublists */  
    29.     FrontBackSplit(head, &a, &b);  
    30.   
    31.     /*Recursively sort the sublists */  
    32.     MergeSort(&a);  
    33.     MergeSort(&b);  
    34.   
    35.     /* answer = merge the two sorted lists together */  
    36.     *headRef = SortedMerge(a, b);  
    37. }  
    38.   
    39. struct node* SortedMerge(struct node* a, struct node* b)  
    40. {  
    41.     struct node* result = NULL;  
    42.   
    43.     /* Base cases */  
    44.     if(a == NULL)  
    45.         return (b);  
    46.     else if(b == NULL)  
    47.         return (a);  
    48.   
    49.     /* Pick either a or b recur */  
    50.     if(a->data <= b->data)  
    51.     {  
    52.         result = a;  
    53.         result->next = SortedMerge(a->next, b);  
    54.     }  
    55.     else  
    56.     {  
    57.         result = b;  
    58.         result->next = SortedMerge(a, b->next);     
    59.     }  
    60.     return (result);  
    61. }  
    62.   
    63. /* UTILITY FUNCTIONS */  
    64. /* Split the nodes of the given list into front and back halves, 
    65.     and return the two lists using the references parameters. 
    66.     If the length is odd, the extra node shold go in the front list. 
    67.     Uses the fast/slow pointer strategy. */  
    68. void FrontBackSplit(struct node* source, struct node** frontRef, struct node** backRef)  
    69. {  
    70.     struct node* fast;  
    71.     struct node* slow;  
    72.   
    73.     if(source == NULL || source->next == NULL)  
    74.     {  
    75.         *frontRef = source;  
    76.         *backRef = NULL;  
    77.     }  
    78.     else  
    79.     {  
    80.         slow = source;  
    81.         fast = source->next;  
    82.   
    83.         /* Advance 'fast' two nodes, and advance 'slow' one node */   
    84.         while(fast != NULL)  
    85.         {  
    86.             fast = fast->next;  
    87.             if( fast != NULL )  
    88.             {  
    89.                 slow = slow->next;  
    90.                 fast = fast->next;  
    91.             }  
    92.         }  
    93.   
    94.         *frontRef = source;  
    95.         *backRef = slow->next;  
    96.         slow->next = NULL;  
    97.     }  
    98. }  
    99.       
    100. /*Function to print nodes in a given linked list*/  
    101. void printList(struct node* node)  
    102. {  
    103.     while( node != NULL )  
    104.     {  
    105.         printf("%d  ", node->data);  
    106.         node = node->next;  
    107.     }  
    108. }  
    109.   
    110. /* Function to insert a node at the begining of the linked list*/  
    111. void push(struct node** head_ref, int new_data)  
    112. {  
    113.     /*allocate node*/  
    114.     struct node* new_node = (struct node*)malloc(sizeof(struct node));  
    115.       
    116.     /*put in the data*/  
    117.     new_node->data = new_data;  
    118.       
    119.     /*link the old list off the new node*/  
    120.     new_node->next = (*head_ref);  
    121.       
    122.     /*move the head to point to the new node*/  
    123.     (*head_ref) = new_node;  
    124. }  
    125.       
    126. /* Drier program to test above functions*/  
    127. int main()  
    128. {  
    129.     /* Start with the empty list */  
    130.     struct node* res = NULL;  
    131.     struct node* a = NULL;  
    132.   
    133.     /* Let us create a unsorted linked lists to test the functions 
    134.        Created lists shall be a: 2->3->20->5->10->15 */  
    135.     push(&a, 15);  
    136.     push(&a, 10);  
    137.     push(&a, 5);  
    138.     push(&a, 20);  
    139.     push(&a, 3);  
    140.     push(&a, 2);   
    141.   
    142.     /* Sort the above created Linked List */  
    143.     MergeSort(&a);  
    144.   
    145.     printf("\n Sorted Linked List is: \n");  
    146.     printList(a);             
    147.   
    148.     return 0;  
    149. }  

    时间复杂度为O(nLogn)。
    貌似MergeSort的时间复杂度为O(nLogn),Split的时间复杂度也为O(nLogn)?当然了,总的时间复杂度还是O(nLogn),但是肯定没有对数组进行归并排序快。

     (7)编写实现strstr函数的代码

    char* strstr(char* src,char* strmatch)

    {

      int len1=strlen(src);

      int len2=strlen(strmatch);

      if(strmatch == NULL || len2 > len1)

        return NULL;

      for(int i=0;i<=len1-len2;i++)

      {

        for(int j=0;j<len2;j++)

        {

          if(src[i+j] != strmatch[j])

            break;

        }

        if ( j==len2)

          return src+i;

      }

        return NULL;

    }

      (8)a写出一个函数来合并两个字符串A和B。字符串A后的几个字节和字符串B的前几个字节重叠

     char* strcpyab(char* s,char* a,char* b,int n)

    {

      int alen=strlen(a);

      int blen=strlen(b);

      if( n > alen || n > blen)

        return error;

      for(int i =0 ;i<alen+blen-n;i++)

      {

        if( i < alen -n)

          s[i] = a[i];

        else

          s[i] = b[i -alen+n];

        

      }

      s[i]='\0';

      return s;

    }

    (9)编写程序,把整数数组放到二叉树中去

      tree-insert(node** root ,node* z)

      {

        node* temp=*root;

        node* tem=NULL;

        while(temp != NULL)

        {

          tem=temp;

          if( z->data < temp ->data)

             temp= temp->left;

          else

             temp=temp->right;  

        }

        if( tem ==NULL)

          *root = z;

        else

        {

            if( z ->data < tem->data)

              tem->left=z;  

            else

              tem->right=z;

        }

      }

    以下字符串函数都是系统自带的,可以直接使用,使用时include <string.h>

    Strcpy:字符串拷贝

    Strlen:字符串长度

    strcmp:字符串的比较

    strncmp:字符串前n个字符的比较

    strncpy:拷贝字符串前n个字符

    strchr:在字符串中查找特定字符首次出现的位置

    strcat:两个字符串相连接

    strstr:从字符串s1中寻找s2第一次出现的位置

    stricmp:比较字符串,且不区分大小

    memcpy:内存缓冲区中字符串的拷贝

    memmove: 内存缓冲区中字符串的移动

    memset:将内存缓冲区中设定为某个字符串

    memcmp:内存缓冲区中字符串的比较

    memicmp: 内存缓冲区中字符串的比较,且不区分大小写

    memchr:与strchr基本相同

    Memmove,memcpy,strcpy的比较:

    memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。

    与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'\0'而结束

    memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

    原型: void *memset(void *buffer, int c, int count);

    用法:#include <string.h>

    功能:把buffer所指内存区域的前count个字节设置成字符c。

    说明:返回指向buffer的指针。

    源码实现:

    void *memset(void *src, int c, size_t count)
    {
     assert(src!=NULL);
     char *tmpsrc=(char*)src;
     while(count--)
      *tmpsrc++ =(char)c;
     return src;
    }

    函数原型: void *memmove(void *dest, const void *src, unsigned int count)

    参数说明:dest为目的字符串,src为源字符串,count为要拷贝的字节数。

    所在库名:#include <string.h>

    函数功能:将字符串src中的前n个字节拷贝到dest中。

    返回说明:dest和src所指内存区域可以重叠,但复制后src内容会被更改。函数返回指向dest的指针。

    源码实现:

    函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。

    注意memmove和memcpy的区别

    void *memmove(void *dest, const void *src, size_t count)

    {

     assert( (dest!=NULL)&&(src!=NULL) );

     char *tmp_dest=(char*)dest;

     char *tmp_src=(char*)src;

     if( tmp_dest+count<tmp_src||tmp_src+count<tmp_dest )

     {// 如果没有重叠区域

     while(count--)

      *tmp_dest++=*tmp_src;

     }

     else

     {// 如果有重叠区域

     tmp_dest+=count-1;

     tmp_src+=count-1;

     while(count--)

      *--tmp_dest=*--tmp_src;

     }

     return dest;

    }

    函数原型: void *memcpy(void *dest, void *src, unsigned int count);

    参数说明:dest为目的字符串,src为源字符串,count为要拷贝的字节数。

    所在库名:#include <string.h>

    函数功能:将字符串src中的前n个字节拷贝到dest中。

    返回说明:src和dest所指内存区域不能重叠,函数返回void*指针。

    //注意memcpy返回的是void*类型

    源码实现:

    附加说明: 指针src和dest所指的内存区域不可重叠

    void *memcpy(void *dest, const void *src, size_t count)

    {

     assert( (dest!=NULL)&&(src!=NULL) );

     char *tmp_dest = (char*)dest;

     char *tmp_src = (char*)src;

     while( count--)//不对是否存在重叠区域进行判断

     *tmp_dest++ = *tmp_src++;

     return dest;

    }

    原型: void *memset(void *buffer, int c, int count);

    用法:#include <string.h>

    功能:把buffer所指内存区域的前count个字节设置成字符c。

    说明:返回指向buffer的指针。

    源码实现:

    void *memset(void *src, int c, size_t count)
    {
     assert(src!=NULL);
     char *tmpsrc=(char*)src;
     while(count--)
      *tmpsrc++ =(char)c;
     return src;
    }

    Char* strcat ( char * dst , const char * src )

    用法:#include <string.h>

    功能:Concatenates src onto the end of dest. Assumes enough space in dest.

    返回结果:The address of "dst"

    源码实现:

    Char* strcat ( char * dst , const char * src )

    {

    char * cp = dst;

    while( *cp !=’\0’)

    cp++;

    while( (*cp++ = *src++)!=’\0’ ) ;

    return( dst );

    }

    Char* strncpy ( char * dst , const char * src ,int count)

    用法:#include <string.h>

    功能:  Copies count characters from the source string to the destination. If count is less than the length of source, NO NULL CHARACTER is put onto the end of the copied string. If count is greater than the length of sources, dest is padded with null characters to length count

    返回结果:The address of "dst"

    源码实现:

    char * strncpy ( char * dest, const char * source, int count )
    {
    char *start = dest;

    while (count && (*dest++ = *source++))
    count--;

    if (count)
    while (--count)
    *dest++ = '\0';

    return(start);
    }

    int strncmp ( char * s1, char * s2, size_t n)

    用法:#include <string.h>

    功能: 比较字符串s1和s2的前n个字符.

    返回结果:

    源码实现:

    int strncmp ( char * s1, char * s2, size_t n)
    {
      if ( !n )//n为无符号整形变量;如果n为0,则返回0
       return(0);
      //在接下来的while函数中
      //第一个循环条件:--n,如果比较到前n个字符则退出循环
      //第二个循环条件:*s1,如果s1指向的字符串末尾退出循环
      //第二个循环条件:*s1 == *s2,如果两字符比较不等则退出循环
      while (--n && *s1 && *s1 == *s2)
      {
         s1++;//S1指针自加1,指向下一个字符
         s2++;//S2指针自加1,指向下一个字符
      }
      return( *s1 - *s2 );//返回比较结果
    }

    
    
  • 相关阅读:
    hdu 1542 Atlantis
    cf C. Cupboard and Balloons
    cf C. Tourist Problem
    hdu 4027 Can you answer these queries?
    hdu 1255 覆盖的面积
    hdu 1698 Just a Hook
    zoj 1610 Count the Colors
    hdu 4302 Holedox Eating
    hdu 4288 Coder
    tsne理论学习
  • 原文地址:https://www.cnblogs.com/zhanglanyun/p/2713285.html
Copyright © 2011-2022 走看看