• 程序面试题——C实现


    平台:win10 x64 +VC6.0

    2019/5/22

    1.合并三个有序的链表

    链表节点定义
    struct node
    {
        int val;
        struct node* next;
    };

    struct node* merge_3 (形参由你定义)
    {
        //这部分是实现
    }

    当输入的有序链表是多个的时候,请给出合并算法,并假设链表个数为m,平均长度为n,请分析时间复杂度

    思路:参看 https://blog.csdn.net/wwxy1995/article/details/82120194

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #define MAXSIZE 20
      4  
      5 typedef int ElemType;
      6 typedef struct Node
      7 {
      8     ElemType data;
      9     struct Node *next;
     10  
     11 }Node;
     12  
     13 typedef struct Node *LinkList;
     14  
     15 // 初始化链表
     16 bool InitList(LinkList *L) // 二级指针
     17 {
     18     *L = (LinkList)malloc(sizeof(Node));  //产生头结点,并使L指向此头节点
     19     if (!(*L))   // 存储分配失败
     20         return false;
     21     (*L)->next = NULL;
     22     return true;
     23 }
     24 void CreateFromTail(LinkList L)
     25 {
     26     Node *r, *s;
     27     int temp;
     28     r = L;  // r指向链表的当前表尾,其初值指向头节点
     29     while (1)
     30     {
     31         scanf("%d", &temp);
     32         if (temp == -1)
     33         {
     34             r->next = NULL;
     35             break;
     36         }
     37         s = (Node*)malloc(sizeof(Node));   // 建立新结点s
     38         s->data = temp;
     39         r->next = s;
     40         r = s;
     41         
     42     }
     43 }
     44  
     45 // 遍历链表
     46 void PrintList(LinkList L)
     47 {
     48     bool flag = true;
     49     Node *p;
     50     p = L->next;
     51     while (p)
     52     {
     53         if (flag)
     54         {
     55             printf("%d", p->data);
     56             flag = false;
     57         }
     58         else
     59             printf(" %d", p->data);
     60         p = p->next;
     61     }
     62     printf("
    ");
     63 }
     64  
     65 LinkList MergeLinkList(LinkList L1, LinkList L2)
     66 {
     67     LinkList L3;
     68     InitList(&L3);
     69     
     70     Node *p, *q, *r, *s;
     71     p = L1->next;
     72     q = L2->next;
     73     r = L3;
     74     while (p&&q)
     75     {
     76         if (p->data < q->data)
     77         {
     78             s = (Node*)malloc(sizeof(Node));
     79             s->data = p->data;
     80             s->next = NULL;
     81             r->next = s;
     82             r = s;
     83             p = p->next;
     84         }
     85         else
     86         {
     87             s = (Node*)malloc(sizeof(Node));
     88             s->data = q->data;
     89             s->next = NULL;
     90             r->next = s;
     91             r = s;
     92             q = q->next;
     93         }
     94     }
     95     
     96     if (p == NULL)
     97     {
     98         r->next = q;
     99     }
    100     if (q == NULL)
    101     {
    102         r->next = p;
    103     }
    104     return L3;
    105 }
    106  
    107 int main()
    108 {
    109     LinkList L1,L2,L3,L4;
    110     InitList(&L1);  // 指针的地址
    111     InitList(&L2);  // 指针的地址
    112     InitList(&L3);  // 指针的地址
    113     InitList(&L4);  // 指针的地址
    114     CreateFromTail(L1);
    115     PrintList(L1);
    116     CreateFromTail(L2);
    117     PrintList(L2);
    118     CreateFromTail(L3);
    119     PrintList(L3);
    120     L4 = MergeLinkList(L1, L2);
    121     PrintList(L4);
    122     L4 = MergeLinkList(L3, L4);
    123     PrintList(L4);
    124     if (L4->next)
    125         PrintList(L4);
    126     else
    127         printf("NULL
    ");
    128  
    129 }
    合并三个有序的链表

    时间复杂度:O(max(length(L1),length(L2),length(L1)+length(L2),length(L3)))

    2019/5/23

    1.“ hello world”转为“ world hello”

    思路:参看 C语言字符串指针(指向字符串的指针)详解:http://c.biancheng.net/view/2012.html

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 void ReverseString(char* s, int from, int to)
     5 {
     6     while(from < to)
     7     {
     8         char t = s[from];
     9         s[from++] = s[to];
    10         s[to--] = t;
    11     }
    12 }
    13 
    14 void LeftRotateString(char* s, int n, int m)
    15 {
    16     m %=n;
    17     ReverseString(s, 0, m-1);
    18     ReverseString(s, m+1, n-1);
    19     ReverseString(s, 0, n-1);
    20 }
    21 
    22 int main(void)
    23 {
    24     int n = 0, m = 0, i;
    25     char s[] = "hello world";
    26     printf("转换前的字符串为:%s
    ", s);
    27     n = strlen(s);
    28     for(i = 0; i < n; i++)
    29         if(s[i] == ' ')
    30             m = i;
    31 
    32     printf("n=%d,m=%d
    ", n,m);
    33     LeftRotateString(s, n, m);
    34     printf("转换后的字符串为:%s
    ", s);
    35     return 0;
    36 }
    字符串反转

    时间复杂度O(n),空间复杂度O(1)

    2.无序数组,找出全部重复元素

    思路:参看《编程之法》1.1字符串的旋转 解法二:三步反转

     1 #include <stdio.h>
     2  
     3 /* 判断一个数组中是否有重复元素,若有,返回位置及元素 */
     4 void hasDup(int arr[], int n)
     5 {
     6     int i, j;
     7     for(i=0; i<n-1; i++)
     8     {    for(j=i+1; j<n; j++)
     9             if(arr[j] == arr[i])
    10             {
    11                 printf("数组中第%d个位置存在重复元素:%d
    ",j,arr[i]);            
    12                 break;    
    13             }
    14             continue;
    15     }
    16 }
    17  
    18 /* 主函数 */
    19 int main()
    20 {
    21     int arr[] = {12, 6, 22, 9, 16, 50, 18, 9, 6, 9};
    22     int n = 10;
    23 
    24     hasDup(arr, n);     
    25  
    26     return 0; 
    27 }
    查找无序数组重复元素及位置

    3.给定数组arr,返回arr的最长递增子序列

    思路:参看左程云 《程序员代码面试指南》  https://blog.csdn.net/hahayikeshu/article/details/85549681

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h> 
     4 int main()
     5 {
     6     int n=1,k[10000],h[1000],g=0,j,t;
     7     char c;
     8     char m[100000];
     9     printf("请输入子序列:");
    10     memset(k,0,sizeof(k)); //把数组k元素全置为零
    11     while(n--)
    12     {
    13         int i=0,l=0;
    14         getchar();//滤掉回车
    15         while((c=getchar())!='
    ')
    16         {
    17             m[i++]=c;//把输入的元素逐个存入数组
    18         }
    19           for(j=0;j<i-1;j++)
    20          {
    21              if(m[j]<m[j+1])
    22              {
    23                  k[l]=k[l]+1;
    24              }
    25              else
    26                 l++;
    27          }
    28          l++;
    29          if(l==2)
    30          {
    31              if(k[0]<k[1])
    32              {
    33                 t=k[0];
    34                 k[0]=k[1];
    35                 k[1]=t;
    36              }
    37          }
    38           if(l>2)
    39          {
    40                for(j=0;j<l-1;j++)
    41                  for(i=0;i<l-j-1;i++)
    42                      if(k[i]<k[i+1])
    43                      {
    44                       t=k[i];
    45                       k[i]=k[i+1];
    46                       k[i+1]=t;
    47                      }
    48          }
    49          
    50          h[g]=k[0];
    51          g++;
    52      }
    53     for(int i=0;i<g;i++)
    54     {
    55         printf("
    ");
    56         printf("单调递增最长子序列长度为:%d
    ",h[i]+1);
    57     }
    58     return 0;  
    59 } 
    输入数组arr,返回最长递增子序列的长度

     参考:最长递增子序列的三种算法  https://blog.csdn.net/love20165104027/article/details/79618367

    4.升序数组,找出最接近定值sum的两个元素,并输出

    思路:二分查找 参看 https://blog.csdn.net/GenuineMonster/article/details/88838346

    问题:long long定义时,如果还用scanf()函数输入,编译器不报错,但是输入的数字完全改变。

    针对这个问题,我也找到了相应的解决办法,请看这篇文章:https://blog.csdn.net/GenuineMonster/article/details/88813979

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int a[1000];//存放升序排列的一列数字
     4 int b[1];//存放要找的数字
     5 int m;//输入要查找的数的个数
     6 long finder(int mx, int mn, int mid, int j)//
     7 {//第一步区分查找的这个数是否在开区间内
     8     if (b[j] <= a[mn] || b[j] >= a[mx])//不在
     9     {
    10         //对内部进行细分,到底是比最小的还小,还是比最大的还大
    11         if (b[j] <= a[mn])  //比最小的还小
    12         {    
    13             printf("%d
    ", a[mn]);
    14             printf("%d
    ", a[mn+1]);
    15         }
    16         else//比最大的还大
    17         {
    18             printf("%d
    ", a[mx-1]);
    19             printf("%d
    ", a[mx]);
    20         }
    21     }
    22     else//位于最小的数字和最大的数字之间
    23     {
    24         //根据mid来分,比mid大还是比mid小,还是和mid相等
    25         if (a[mn]<b[j] && b[j]<a[mid])//比mid小
    26         {
    27             if (mid - mn != 1)
    28             {
    29                 mx = mid - 1;//将mx替换为mid
    30                 mid = (mn + mx) / 2;//重新计算mid下标
    31                 finder(mx, mn, mid, j);
    32             }
    33             else
    34             {
    35                 if (a[mid] - b[j]>b[j] - a[mn])//比较距离
    36                     printf("%d
    ", a[mn]);
    37                 else if (a[mid] - b[j]<b[j] - a[mn])
    38                     printf("%d
    ", a[mid]);
    39                 else
    40                     printf("%d %d
    ", a[mn], a[mid]);
    41             }
    42  
    43         }
    44         else if (a[mid]<b[j] && b[j]<a[mx])//比mid大
    45         {
    46  
    47             if (mx - mid != 1)
    48             {
    49                 mn = mid;//重新计算mn
    50                 mid = (mn + mx) / 2;//重新计算mid下标
    51                 finder(mx, mn, mid, j);
    52             }
    53             else
    54             {
    55                 if (b[j] - a[mid]>a[mx] - b[j])
    56                     printf("%d
    ", a[mx]);
    57                 else if (b[j] - a[mid]<a[mx] - b[j])
    58                     printf("%d
    ", a[mid]);
    59                 else
    60                     printf("%d %d
    ", a[mid], a[mx]);
    61             }
    62         }
    63         else//和mid相等
    64         {
    65             printf("%d
    ", b[j]);
    66             if((b[j]-a[mid-1]) >= (a[mid+1]-b[j]))
    67                 printf("%d
    ", a[mid+1]);
    68             else
    69                 printf("%d
    ", a[mid-1]);
    70         }
    71     }
    72     return 0;
    73 }
    74 int main()
    75 {
    76     int j = 0;//用作函数循环的
    77     int n;//输入非降序序列的长度
    78     printf("请输入非降序序列的长度:");    
    79     scanf("%d", &n);
    80     printf("请输入非降序序列:");    
    81     for (int i = 0; i<n; i++) //循环输入n个数字
    82         scanf("%d", &a[i]);
    83     //scanf("%d", &m);    //输入要查询的数字个数
    84     //for (int i = 0; i<m; i++) //循环输入要查找的数,存在b[i]中
    85     printf("请输入要查找的元素sum:");    
    86         scanf("%d", &b[0]);
    87     int mx = n - 1, mn = 0;
    88     int mid = (mx + mn) / 2;
    89 //    for (j = 0; j<m; j++)//循环调用函数,把b[j]中存储的所有要找的数字找完
    90         finder(mx, mn, mid, 0);
    91     //system("pause");
    92     return 0;
    93  
    94 }
    输入一升序数组,返回最接近给定值的两个元素
  • 相关阅读:
    LINUX常见服务列表
    xinetd服务管理
    System V启动脚本启动的服务
    linux系统服务
    proc文件系统
    sar网络统计数据
    sar磁盘I/O统计数据
    sar-CPU统计数据
    linux性能监视工具sar
    考试认证
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/ProgramOfInterviewQuestion1.html
Copyright © 2020-2023  润新知