80道面试题及其解法(三)

来源:互联网 发布:网络连接正常上不了网 编辑:程序博客网 时间:2024/06/08 20:14

现有LA与LB两个链表,已升序排列。将LA与LB合并后也按升序排列.

 

设指针pa与pb分别均指向LA与LB当前的结点,那么只需要每次比较当前的这两个节点,谁小就把谁加入到LC(新链表)中,然后小的这个链表的指针继续后移。这样最坏的复杂度也只是O(LENA+LENB),算法2的实现如下:

 

[cpp] view plain copy
 print?
  1. //结点结构体定义  
  2. struct LNode{  
  3.     int data;  
  4.     LNode *next;  
  5. };  
  6. typedef LNode * LinkList;  
  7. void main()  
  8. {//函数声明  
  9.  void creat_list(LinkList &L,int n);  
  10.  void merge_list(LinkList &La,LinkList &Lb,LinkList &Lc);  
  11.  void print_list(LinkList L);  
  12.  //主函数开始  
  13.  int n1,n2;  
  14.  LinkList La,Lb,Lc;  
  15.  printf("建立La链表开始:请先输入要建立的结点个数\n");  
  16.  scanf("%d",&n1);  
  17.  creat_list(La,n1);  
  18.  printf("La链表信息如下:\n");  
  19.  print_list(La);  
  20.  printf("建立Lb链表开始:请先输入要建立的结点个数\n");  
  21.  scanf("%d",&n2);  
  22.  creat_list(Lb,n2);  
  23.  printf("Lb链表信息如下:\n");  
  24.  print_list(Lb);  
  25.  printf("合并完两链表后如下:\n");  
  26.  merge_list(La,Lb,Lc);  
  27.  print_list(Lc);  
  28. }  
  29. void creat_list(LinkList &L,int n)  
  30. {   int i;  
  31.     LinkList p,q;  
  32.     L=(LinkList)malloc(sizeof(LNode));  
  33.     L->next=NULL;//建立头结点  
  34.     q=L;  
  35.     for (i=1;i<=n;i++)  
  36.     {p=(LinkList)malloc(sizeof(LNode));  
  37.     printf("请输入第%d个节点的数据:",i);  
  38.     scanf("%d",&p->data);  
  39.     q->next=p;  
  40.     q=q->next;//q后移  
  41.     }  
  42.     p->next=NULL;//最后一个节点是尾结点  
  43. }  
  44.  void merge_list(LinkList &La,LinkList &Lb,LinkList &Lc)  
  45.  {LinkList pa,pb,pc;  
  46.   pa=La->next;pb=Lb->next;//a,b链表均指向自己的第一个结点  
  47.   pc=Lc=La;//Lc链表自始至终就没有建立过,实际上LC就是借助指针去连接la和lb中的结点  
  48.   while(pa&&pb)//不指向末尾  
  49.   {  
  50.       if (pa->data<=pb->data)//插入La  
  51.       {pc->next=pa;  
  52.        pc=pa;//pc后移  
  53.        pa=pa->next;//La后移  
  54.       }  
  55.       else  
  56.       {  
  57.         pc->next=pb;  
  58.         pc=pb;  
  59.         pb=pb->next;  
  60.       }  
  61.   }//结束该循环后应该会剩下一个链表没合并完(假设俩个链表长度不一样)  
  62.   pc->next=pa?pa:pb;//剩余  
  63.   
  64.  }  
  65. void print_list(LinkList L)  
  66. {  
  67.   LinkList p=L->next;//指向第一个结点  
  68.   while(p)  
  69.   {  
  70.       printf("%3d",p->data);  
  71.       p=p->next;  
  72.   }  
  73.   printf("\n");  
  74. }



  75. 题目描述:

         一个循环有序数组(如:3,4,5,6,7,8,9,0,1,2),不知道其最小值的位置,要查找任一数值的位置。要求算法时间复杂度为log2(n)。


    问题分析:

        我们可以把循环有序数组分为左右两部分(以mid = (low+high)/ 2为界),由循环有序数组的特点知,左右两部分必有一部分是有序的,我们可以找出有序的这部分,然后看所查找元素是否在有序部分,若在,则直接对有序部分二分查找,若不在,对无序部分递归调用查找函数。

    代码如下:

        #include <iostream>

        using namespace std;

        int binarySearch(int a[],int low,int high,int value)  //二分查找
        {
            if(low>high)
                return -1;

            int mid=(low+high)/2;

            if(value==a[mid])
                return mid;
            else if(value>a[mid])
                return binarySearch(a,mid+1,high,value);
            else
                return binarySearch(a,low,mid-1,value);
        }

        int Search(int a[],int low,int high,int value)     //循环有序查找函数
        {
            int mid=(low+high)/2;

            if(a[mid]>a[low])       //左有序
            {
                if(a[low]<=value && value<=a[mid] )        //说明value在左边,直接二分查找
                {
                    return binarySearch(a,low,mid,value);
                }

                else                                       //value在右边
                {
                    return Search(a,mid+1,high,value);
                }
            }
            else                    //右有序
            {
                if(a[mid]<=value && value<=a[high])
                {
                    return binarySearch(a,mid,high,value);
                }
                else
                {
                    return Search(a,low,mid-1,value);
                }
            }
        }

        int main()
        {
            int a[]={3,4,5,6,7,8,9,0,1,2};

            cout<<Search(a,0,9,0)<<endl;

            return 0;
        }

      

二叉树学习之非递归遍历


二叉树递归遍历可谓是学过数据结构的同仁都能想一下就能写出来,但在应聘过程我们常常遇到的是写出一个二叉树非递归遍历函数,接着上篇文章写二叉树的非递归遍历,先难后易,一步一步的来.

  先上代码:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "binarytree.h"  
  2. #include <stack>  
  3. #include <queue>  
  4.   
  5. #ifndef RECU  
  6. #warning("RECU is not defined")  
  7.   
  8. /** 
  9.  *前序遍历(根左右) 
  10.  * 
  11.  *1、当前节点为非空,访问当前节点,压栈其右子节点,考虑其左子节点 
  12.  *2、当前节点为NULL,出栈 
  13.  * 
  14.  *@param t to visit 
  15.  *@param visit point to a func 
  16.  */  
  17. void pre_order(link t, void (*visit)(link))  
  18. {  
  19.     std::stack<link> myStack;  
  20.   
  21.     while( t || !myStack.empty() ) {  
  22.   
  23.         if ( t ) {  
  24.             visit(t);  
  25.             myStack.push(t->rchild);  
  26.             t = t->lchild;  
  27.         } else {  
  28.             t = myStack.top();  
  29.             myStack.pop();  
  30.         }  
  31.     }  
  32. }  
  33.   
  34. /** 
  35.  *中序序遍历(左根右) 
  36.  * 
  37.  *1、当前节点为非空,在访问当前节点前要先访问其左子节点, 
  38.  *   压栈当前节点,判断其左子结点,一直压栈左子节点 
  39.  *2、当前节点为NULL,出栈访问,其左子结点比当前节点出栈访问早, 
  40.  *   此时当前节点是其右节点的父节点的角色,考虑其右节点 
  41.  * 
  42.  *在遍历过程中角色转换很重要 
  43.  * 
  44.  *@param t to visit 
  45.  *@param visit point to a func 
  46.  */  
  47. void in_order(link t, void (*visit)(link))  
  48. {  
  49.     std::stack<link> myStack;  
  50.   
  51.     while( t || !myStack.empty() ) {  
  52.   
  53.         if ( t ) {  
  54.             myStack.push(t);  
  55.             t = t->lchild;  
  56.         } else {  
  57.             t = myStack.top();  
  58.             myStack.pop();  
  59.             visit(t);  
  60.             t = t->rchild;  
  61.         }  
  62.     }  
  63. }  
  64.   
  65. /** 
  66.  *后序遍历(左右根) 
  67.  * 
  68.  *1、由于在访问当前树的根结点时,应先访问其左、右子树,因而先将根结点入栈, 
  69.  *   接着将右子树也入栈,然后考虑左子树,重复这一过程直到某一左子树为空 
  70.  *2、如果当前考虑的子树为空, 
  71.  *   1.若栈顶不为空,说明第二栈顶对应的树的右子树未处理, 
  72.  *   则弹出栈顶,下次循环处理,并将一空指针入栈以表示其另一子树已做处理; 
  73.  *   2.若栈顶也为空树,说明第二栈顶对应的树的左右子树或者为空,或者均已做处理, 
  74.  *   直接访问第二栈顶的结点,访问完结点后,若栈仍为非空,说明整棵树尚未遍历完, 
  75.  *   则弹出栈顶,并入栈一空指针表示第二栈顶的子树之一已被处理。 
  76.  * 
  77.  *@param t to visit 
  78.  *@param visit point to a func 
  79.  */  
  80. void post_order(link t, void (*visit)(link))  
  81. {  
  82.     std::stack<link> myStack;  
  83.   
  84.     while( 1 ) {  
  85.         if ( t ) {  
  86.             myStack.push(t);  
  87.             myStack.push(t->rchild);  
  88.             t = t->lchild;  
  89.         } else {  
  90.             t = myStack.top();  
  91.             myStack.pop();  
  92.             if (!t) {  
  93.                 t = myStack.top();  
  94.                 myStack.pop();  
  95.                 visit(t);  
  96.                 if (myStack.empty())  
  97.                     break;  
  98.                 t = myStack.top();  
  99.                 myStack.pop();  
  100.             }  
  101.             myStack.push(NULL);  
  102.         }  
  103.     }  
  104. }  
  105. #endif  
  106.   
  107. /** 
  108.  *层遍历 
  109.  * 
  110.  *@param t to visit 
  111.  *@param visit point to a func 
  112.  */  
  113. void level_order(link t, void (*visit)(link))  
  114. {  
  115.     std::queue<link> myQueue;  
  116.   
  117.     if (t) {  
  118.         myQueue.push(t);  
  119.         while( !myQueue.empty() ) {  
  120.             link tmp = myQueue.front();  
  121.             myQueue.pop();  
  122.             visit(tmp);  
  123.             if (tmp->lchild != NULL)  
  124.                 myQueue.push(tmp->lchild);  
  125.             if (tmp->rchild != NULL)  
  126.                 myQueue.push(tmp->rchild);  
  127.         }  
  128.     }  
  129. }  


面试题整理-矩阵查找元素


需要在矩阵中查找元素。这个矩阵的排列如下:


每一行都是有序的。每一列都是有序的。

比如一个小矩阵。


10 30

20 80


现在,我们需要在一个这样N * M的矩阵中找到一个元素,并返回其位置。


思路

首先,这个题不太适合二分查找。因为并不能保证第二行的元素都一定比第一行的任意元素大。

所以应该是很难找到O(lgN)的算法。


每次都是取右上角的元素v与x(我们要查找的元素)进行比较较:

    如果发现v > x,由于v所在列肯定比x大。所以v所在列可以舍弃。

    如果发现v < x,由于v所在行肯定比x小。所以v所在行可能舍弃。

最后余下的,可能是一行,也可能是一列。总之可以利用二分查找来实现了。效率O(min(N, M)) + log(abs(M-N)).

解题

这里直接粘出代码。

[cpp] view plain copy
  1. int find(int **a, const int row, const int col, const int x, int *rpos, int *cpos) {  
  2.     //右上角为起始点.  
  3.     int from_row = 0, from_col = col - 1, v;  
  4.     int b, e, mid;  
  5.     *rpos = *cpos = -1;  
  6.   
  7.     while (from_row < row && from_col >= 0) {  
  8.         v = a[from_row][from_col];  
  9.         if (v == x) {  
  10.             *rpos = from_row;  
  11.             *cpos = from_col;  
  12.             return 1;  
  13.         }  
  14.         from_row += x > v;  
  15.         from_col -= v > x;  
  16.     }  
  17.     //最后剩下一行  
  18.     if (from_row == (row - 1) && from_col != 0) {  
  19.         b = 0, e = from_col + 1;  
  20.         while (b < e) {  
  21.             mid = b + ((e-b)>>1);  
  22.             v = a[from_row][mid];  
  23.             if (x == v) {  
  24.                 *rpos = from_row;  
  25.                 *cpos = mid;  
  26.                 return 1;  
  27.             } else if (v > x) e = mid;  
  28.             else b = mid + 1;  
  29.         }  
  30.         return 0;  
  31.     }  
  32.     //最后剩下一列  
  33.     if (from_col == 0 && from_row != (row - 1)) {  
  34.         b = from_row, e = row;  
  35.         while (b < e) {  
  36.             mid = b + ((e-b)>>1);  
  37.             v = a[mid][0];  
  38.             if (v == x) {  
  39.                 *rpos = mid;  
  40.                 *cpos = from_col;  
  41.                 return 1;  
  42.             } else if (v > x) e = mid;  
  43.             else b = mid + 1;  
  44.         }  
  45.         return 0;  
  46.     }  
  47.     //最后只剩下一个点  
  48.     if (a[from_row][from_col] == x) {  
  49.         *rpos = from_row;  
  50.         *cpos = from_col;  
  51.         return 1;  
  52.     }  
  53.     return 0;  
  54. }  

这里写一个测试程序,如果有错,会输出Error。


大数整数乘法方法
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * bigmuilty(char*muiltied,int len1,char *muilty,int len2)//muiltied 为被乘数,len1为其长。muilty为乘数,len2为其长
{
   int len;
   int i=0;
   int j=0;
   int k=0;
   int tmp_result=0;
   int carry=0;
   char* result;
   len=len1+len2; //两个数相乘他们的最大长度为乘数与被乘数的长度和
   result=(char*)calloc(len,1);//动态分配内存
   for(i=0;i<len2;i++)//用乘数的每一位去乘以被乘数
   {
     for(j=0;j<len1;j++)
     {
        tmp_result=muilty[len2-i-1]*muiltied[len1-j-1];//得到零时结果
        result[j+i]+=tmp_result;//如果以0为起始标号,被乘数和乘数下标分别从右往左依次增加,则结果存放的位置为j+i
     }
     for(k=0;k<=j+i-1;k++)//整理结果,使每位的值在0-9之间
     {
                
        if(result[k]>9)
        {
           carry=result[k]/10;
           result[k]=result[k]%10;
           result[k+1]+=carry;
        }
     }
   }
return result;
}
int main()
{
   int len1=0;
   int len2=0;
   int len;
   int i=0;
   int num='0';
   char *result;
   char muiltied[BUFSIZ];//被乘数存放位置
   char muilty[BUFSIZ];
   printf("entry muiltied :  ");
   scanf("%s",muiltied);
   printf("\nentry muilty :  ");
   scanf("%s",muilty);
   len1=strlen(muiltied);
   len2=strlen(muilty);
   len=len1+len2;
   for(i=0;i<len1;i++)
   {
       muiltied[i]=muiltied[i]-num;
   }
   for(i=0;i<len2;i++)
   {
      muilty[i]=muilty[i]-num;
   }
   result=bigmuilty(muiltied,len1,muilty,len2);
   i=len-2;
   printf("\nresult : ");
   if(result[len-1]>0)
   {
     printf("%c",result[len-1]+num);
   }
   while(i>=0)
   {
      printf("%c",result[i]+num);
   i--;
   }
   printf("\n");
   free(result);
   return 0;
}


1.Copyright 1990 Software Development Systems, Inc.
1
2
3
4
5
6
7
8
9
10
11
12
char *strstr(const char *s1,const char *s2)
{
 int len2;
 if(!(len2=strlen(s2)))//此种情况下s2不能指向空,否则strlen无法测出长度,这条语句错误
     return(char*)s1;
 for(;*s1;++s1)
 {
     if(*s1==*s2 && strncmp(s1,s2,len2)==0)
     return(char*)s1;
 }
 return NULL;
}
2.Copyright 1986 - 1999 IAR Systems. All rights reserved
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
char *strstr(constchar*s1,constchar*s2)
{
    int n;
    if(*s2)
    {
        while(*s1)
        {
            for(n=0;*(s1+n)==*(s2+n);n++)
            {
                if(!*(s2+n+1))
                    return(char*)s1;
            }
            s1++;
        }
        return NULL;
    }
    else
        return (char*)s1;
}


0 0
原创粉丝点击