华为机试--简单题(一)

2023-11-15

HJ14 字符串排序

知识点:字符串;排序
描述
给定 n 个字符串,请对 n 个字符串按照字典序排列。
数据范围: 1≤n≤1000 ,字符串长度满足1≤len≤100
输入描述:
输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母。
输出描述:
数据输出n行,输出结果为按照字典序排列的字符串。

示例1

输入:
9
cap
to
cat
card
two
too
up
boat
boot
输出:
boat
boot
cap
card
cat
to
too
two
up

代码:

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

int main(void)
{
    int n=0,i,j;
    char temp[100];
    scanf("%d", &n);
    char words[n][100];
    for(i=0;i<n;i++){   /*输入所有字符串*/
        scanf("%s", words[i]);
    }
    for(i=0;i<n-1;i++){         /*冒泡排序*/
        for(j=0;j<n-i-1;j++){
            if(strcmp(words[j],words[j+1])>0){
                strcpy(temp,words[j]);
                strcpy(words[j],words[j+1]);            
                strcpy(words[j+1],temp);
            }
        }
    }
    //printf("-----------------------------------------------\r\n");
    for(i=0;i<n;i++){       /*输出*/
        printf("%s\r\n",words[i]);
    }
    return 0;

}
---------------------------结果----------------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test 
5
cap
to
cat
too
boot
boot
cap
cat
to
too
song@song-virtual-machine:~/C_Program/interview_code$ 

HJ54 表达式求值

知识点: 字符串;基础数学;栈
描述
给定一个字符串描述的算术表达式,计算出结果值。
输入字符串长度不超过 100 ,合法的字符包括 ”+, -, *, /, (, )” , ”0-9” 。

数据范围:运算过程中和最终结果均满足∣val∣≤2^31-1, 即只进行整型运算,确保输入的表达式合法
输入描述:
输入算术表达式
输出描述:
计算出结果值
示例1
输入:400+5
输出:405
代码:

#include<stdio.h>
#include<string.h>
#include <malloc.h>
int pos;
/*检查是否为数字*/
int check(char c)
{
    if(c >= '0' && c <= '9'){
        return 1;
    }
    return 0;
}
/*开始计算*/
int compute(char *data)
{
    int len = strlen(data);
    int num = 0;
    int stack[100] = {0};
    int top = -1;
    char flag = '+';
    while(pos < len){
        /*进入括号时,就相当于递归一次当前的方法*/
        if(data[pos] == '{' || data[pos] == '[' || data[pos] == '('){
            pos ++;
            num = compute(data);
        }
        /*当前字符为数字时,则计算当前的数字*/
        while(pos < len && check(data[pos])){
            num = num * 10 + data[pos] - '0';
            pos++;
        }
        /*开始计算当前的数字*/
        switch(flag){
            case '+':
                ++top;
                stack[top] = num;
                break;
            case '-':
                ++top;
                stack[top] = -num;
                break;
            case '*':
                stack[top] *= num;
                break;
            case '/':
                stack[top] /= num;
                break;
        }
        
        num = 0;
        flag = data[pos];
        pos++;
        /*结束的标志,退出当前的递归,返还上一个运算*/
        if(flag == '}' || flag == ']' || flag == ')' || flag == '\n'){
            break;
        }
    }
    int res = 0;
    for(int i = 0;i<=top;i++){
        res += stack[i];
    }
    return res;
    
}

int main(void)
{
    char *s = (char *)malloc(sizeof(char)*100);
    memset(s, 0, sizeof(char)*100);
    while(fgets(s,sizeof(char)*100,stdin) != NULL){
        pos = 0;
        printf("%d\n",compute(s));
    }
    free(s);
    s=NULL;
    return 0;
}
-------------------结果------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
2*3-1
5
2*(3-1)
4
^C
song@song-virtual-machine:~/C_Program/interview_code$
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

int pos;

int check(char st)
{
    if(st>='0'&&st<='9'){
        return 1;
    }else{
        return 0;
    }
}
int compute(char *data)
{
    int len = strlen(data);
    int num = 0;
    char flag='+';
    int top=-1;
    int stack[100] = {0};
    while(pos<len){
        if(data[pos]=='{'||data[pos]=='['||data[pos]=='('){
            pos++;
            num=compute(data);
        }
        while(pos<len&&check(data[pos])){
            num=num*10+data[pos]-'0';
            pos++;
        }
        switch(flag){
            case '+': 
                ++top;
                stack[top]=num;
                break;
            case '-': 
                ++top;
                stack[top]=-num;
                break;
            case '*': 
                stack[top]*=num;
                break;
            case '/': 
                stack[top]/=num;
                break;
        }
        num=0;
        flag=data[pos];
        pos++;
        if(flag=='}'||flag==']'||flag==')'||flag=='\n'){
            break;
        }
    }
    int res=0;
    for(int i=0;i<=top;i++){
        res=res+stack[i];
    }
    return res;
}

int main(void)
{
    char str[100];
    while(scanf("%s",str)!= EOF){
        pos=0;
        printf("%d\n",compute(str));
    }

HJ85 最长回文子串

知识点: 字符串;穷举
描述
给定一个仅包含小写字母的字符串,求它的最长回文子串的长度。
所谓回文串,指左右对称的字符串。
所谓子串,指一个字符串删掉其部分前缀和后缀(也可以不删)的字符串
数据范围:字符串长度1≤s≤350
进阶:时间复杂度:O(n) ,空间复杂度:O(n)
输入描述:
输入一个仅包含小写字母的字符串
输出描述:
返回最长回文子串的长度
示例1
输入:cdabbacc
输出:4
说明:
abba为最长的回文子串
代码:
方法1:虽然复杂度为O(n^2),但是好理解,马拉车法不好理解

#include<stdio.h>
#include<stdlib.h>
#include <math.h>
#include <string.h>
char* insert(char* str, int n) 
{
    char* res = (char*)malloc(sizeof(char) * (2 * n + 1));
    int i;
    for(i=0;*(str+i)!='\0';i++){
        res[2 * i] = '#';
        res[2 * i + 1] = str[i];
    }
    res[2 * i] = '#';
    return res;
}
int getvalue(char* str, int n) 
{
    int len=1,max=1;
    for(int i=1; i<n; i++){
        for(int j=1;(j<=i)&&(j<=n-i);j++){
            //printf("*  ");
      //      printf("%c %c  %c         ",*(str+i-j),*(str+i),*(str+i+j));
            if(*(str+i-j)==*(str+i+j)){
                len++;
            }else{
                break;
            }
        }
     //   printf("\n");
        if(len>max){
            max=len;
        }
        len=1;
    }
    return max-1;
}
int main(void) 
{
    char str[351];
    while (~scanf("%s", str)) {
        int len=strlen(str);
        printf("%d\n", len);
        char *ptr1 = insert(str, len);
        printf("%s\n",ptr1);
        printf("%d\n",getvalue(ptr1, 2*len+1));
        free(ptr1);
    }
}

HJ102 字符统计

知识点:字符串;排序;哈希
描述
输入一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASCII码由小到大排序输出。
数据范围:字符串长度满足1≤len(str)≤1000
输入描述:
一个只包含小写英文字母和数字的字符串。

输出描述:
一个字符串,为不同字母出现次数的降序表示。若出现次数相同,则按ASCII码的升序输出。
示例1
输入:aaddccdc
输出:cda
说明:样例里,c和d出现3次,a出现2次,但c的ASCII码比d小,所以先输出c,再输出d,最后输出a.
代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
    char str[1000]={'\0'};
    while(scanf("%s",str)!=EOF){
        int max=0;
        int buf[128]={0};
        int len=strlen(str);
        for(int i=0;i<len;i++){
            buf[str[i]]++;
            if(buf[str[i]]>max){
                max=buf[str[i]];
            }
        }

        for(int i=max;i>0;i--){
            for(int j=0;j<128;j++){
                if(i==buf[j]){
                    printf("%c",j);
                }
            }
        }
        printf("\n");
    }
}
----------------------结果--------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
aaddccdc
cda
aaccd
acd
aacccd
cad
^C
song@song-virtual-machine:~/C_Program/interview_code$

HJ53 杨辉三角的变形

知识点:基础数学
描述
以上三角形的数阵,第一行只有一个数1,以下每行的每个数,是恰好是它上面的数、左上角数和右上角的数,3个数之和(如果不存在某个数,认为该数就是0)。
求第n行第一个偶数出现的位置。如果没有偶数,则输出-1。例如输入3,则输出2,输入4则输出3,输入2则输出-1。
数据范围:1≤n≤10^9
输入描述:
输入一个int整数
输出描述:
输出返回的int值

示例1
输入:4
输出:3

代码:
方法1:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
int main(void)
{
    int n=0;
    while(scanf("%d",&n)!=EOF){
        int i=0,j=0,m=0;
        m=2*n-1;
        int **buf=(int **)malloc(sizeof(int *)*n);      /*数组的行*/
        for(i=0;i<n;i++){           /*数组的列,并初始化为0*/
            buf[i]=(int *)malloc(sizeof(int)*m);    
            memset(buf[i],0,m*sizeof(int));
        }

        buf[0][m/2]=1;    /* 第一行 */
        for(i=1;i<n;i++){
            buf[i][m/2-i]=1;
            buf[i][m/2+i]=1;
            for(j=m/2-i+1;j<m/2+i;j++){
                buf[i][j]=buf[i-1][j]+buf[i-1][j-1]+buf[i-1][j+1];
            }
        }

        // for(i=0;i<n;i++){        /*打印三角形*/
        //     for(j=0;j<m;j++){
        //         if(buf[i][j]==0){
        //        //printf("%3d ",buf[i][j]);
        //         printf("    ");  /*4个空格,为了美观*/             
        //         }else{
        //         printf("%3d ",buf[i][j]);
        //         }
        //     }
        //     printf("\n");
        // }
        if(n==1||n==2){
            printf("%d\n",-1);
        }else if(n>=3){
            for(i=0;i<(2*n-1)/2;i++){
                if(buf[n-1][i]%2==0){
                    printf("%d\n",i+1);
                    break;
                }
            }
        }
        for(i=0;i<n;i++){
            free(buf[i]);
        }
        free(buf);
    }
    return 0;
}

方法2:其实没有必要求出来这个数组,只要求求得是第一个偶数
-1 -1 2 3 2 4 2 3 2 4 2 3 2 4

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
int main(void)
{
    int n=0,num=0,buf[4]={2,3,2,4};
    while(scanf("%d",&n)!=EOF){
        if(n==1||n==2){
            num=-1;
        }else if(n>2){
            num=buf[(n-3)%4];
        }
        printf("%d\r\n",num);
    }
    return 0;
}

HJ91 走方格的方案数

知识点:动态规划;基础数学
描述
请计算n*m的棋盘格子(n为横向的格子数,m为竖向的格子数)从棋盘左上角出发沿着边缘线从左上角走到右下角,总共有多少种走法,要求不能走回头路,即:只能往右和往下走,不能往左和往上走。
注:沿棋盘格之间的边缘线行走
数据范围:1≤n,m≤8
输入描述:
输入两个正整数n和m,用空格隔开。(1≤n,m≤8)
输出描述:
输出一行结果
示例1
输入:2 2
输出:6

代码:
方法1:
动态规划
分析:

1,	dp[i][j]:表示从左上角到i行j列格子的右下角的走法
2,	递推关系:
dp[i][j]=dp[i-1][j]+dp[i][j-1]
3,寻找初值,dp[1][1]=dp[0][1]+dp[1][0]=2;  dp[0][1]=dp[1][0]=1;
dp[1][2] = dp[0][2]+dp[1][1]=3,  dp[0][2]=1
dp[2][1] = dp[1][1]+dp[2][0]=3,  dp[2][0]=1
所以dp[i][0]=1;dp[0][i]=1;

代码:

      /*方法1,动态规划做法*/
#include<stdio.h>
int main(void)
{
    int n, m;
 
    while(scanf("%d %d", &n, &m) != EOF) {
        int i, j, dp[n+1][m+1];
 
        for(i=0; i<=n; i++) {
            for(j=0; j<=m; j++) {
                if(i == 0 && j == 0) {
                    dp[i][j] = 1;
                    continue;
                }
                if(i == 0)
                    dp[i][j] = dp[i][j-1];
                else if(j == 0)
                    dp[i][j] = dp[i-1][j];
                else
                    dp[i][j] = dp[i][j-1] + dp[i-1][j];
            }
        }
        printf("%d\n", dp[n][m]);
    }
}
------------------------------结果---------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
2 2 
6
1 3
4
^C
song@song-virtual-machine:~/C_Program/interview_code$
                             /*方法2,递归做法*/
#include<stdio.h>
int fun(int m,int n)
{
    if(m==0||n==0)
        return 1;
    else
        return fun(m,n-1)+fun(m-1,n);
}
int main(void)
{
    int m,n;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        printf("%d\n",fun(n,m));
    }
}

函数功能:返回走法数。
结束条件:找下规律不难发现:当n或m有一个为1时,走法数等于较大的那个数加一,所以结束条件可以设置为

if(n==1||m==1)
		return (n+1>m+1)?n+1:m+1;

等价关系:要走到右下角必须经过最后一个方格的左下角或右上角,所以可以把所有走法分为走到最后一个方格的左下角和走到最后一个方格的右上角,即f(n,m)=f(n,m-1)+f(n-1,m)。

#include<stdio.h>

int f(int n,int m)
{
    if(n==1||m==1)
        return (n+1>m+1)?n+1:m+1;
    else
        return f(n-1,m)+f(n,m-1);
}
int main(void)
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        printf("%d\n",f(n,m));
    }
    return 0;
}
-------------------结果--------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
2 2
6
1 3
4
^C
song@song-virtual-machine:~/C_Program/interview_code$ 

HJ108 求最小公倍数

知识点:递归;基础数学
描述
正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。
数据范围:1≤a,b≤100000
输入描述:
输入两个正整数A和B。

输出描述:
输出A和B的最小公倍数。
示例1
输入:5 7
输出:35
示例2
输入:2 4
输出:4
代码:
最小公倍数=两数的乘积/最大公约(因)数,解题时要避免和最大公约(因)数问题混淆。

辗转相除法, 又名欧几里德算法(Euclidean algorithm),是求最大公约数的一种方法。它的具体做法是:用较小数除较大数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。

#include <stdio.h>
#include <stdlib.h>
/*最大公因数*/
int greatest_common_factor(int a,int b) 
{
    if(a<b){
        int temp = a;
        a = b;
        b=temp;
    }
    while(a%b){
        int temp=a;
        a=b;
        b=temp%b;
    }
    return b;
}

int main(void)
{
    int m,n;
    while(scanf("%d %d",&m,&n)!=EOF){
        printf("%d\n",(m*n)/greatest_common_factor(m,n));

    }

}
---------------------------------结果---------------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
2 3
6
150 200
600
^C
song@song-virtual-machine:~/C_Program/interview_code$

HJ35 蛇形矩阵

知识点:数组
描述
蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。例如,当输入5时,应该输出的三角形为:

1 3 6 10 15
2 5 9 14
4 8 13
7 12
11

输入描述:
输入正整数N(N不大于100)
输出描述:
输出一个N行的蛇形矩阵。
示例1
输入:4
输出:

1 3 6 10
2 5 9
4 8
7

代码:

#include <stdio.h>
#include <malloc.h>
int main(void)
{
    int n;
    while(scanf("%d", &n) != EOF){
        int count = 0;
        int **buf=(int **)malloc(n*sizeof(int *));
        for(int i=0; i<n; i++){
            buf[i]=(int *)malloc(n*sizeof(int));
        }
        for(int i=0; i<n; i++){
            for(int j=i; j>=0; j--){
                count++;
                buf[j][i-j]=count;
            }
        }

        for(int i=0; i<n; i++){
            for(int j=0; j<n-i; j++){
                printf("%3d",buf[i][j]);
            }
            printf("\n");
        }

        for(int i=0; i<n; i++){
            free(buf[i]);
        }
        free(buf);
    }
}

HJ80 整型数组合并

知识点:排序;数组;哈希
描述
题目标题:
将两个整型数组按照升序合并,并且过滤掉重复数组元素。输出时相邻两数之间没有空格。
输入描述:
输入说明,按下列顺序输入:
1 输入第一个数组的个数
2 输入第一个数组的数值
3 输入第二个数组的个数
4 输入第二个数组的数值
输出描述:
输出合并之后的数组
示例1

输入:
3
1 2 5
4
-1 0 3 2
输出:-101235

代码:

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

int cmp(const void* a,const void* b)
{
   return ( *(int*)a - *(int*)b);
}

int main(void)
{
    int s1,s2;
    while(scanf("%d",&s1)!=EOF){
        int *n1=(int *)malloc(s1*sizeof(int));
        for(int i=0;i<s1;i++){
            scanf("%d",&n1[i]);
        }
        scanf("%d",&s2);
        n1=(int *)realloc(n1,(s1+s2)*sizeof(int));
        for(int i=s1;i<s1+s2;i++){
            scanf("%d",&n1[i]);
        }
        qsort(n1,s1+s2,sizeof(int),cmp);
        int old=n1[0];
        printf("%d",n1[0]);
        for(int i=1;i<s1+s2;i++){
            if(n1[i]!=old){
                old=n1[i];
                printf("%d",n1[i]);
            }
        }
        printf("\n");
        free(n1);
    }
    return 0;
}

HJ6 质数因子

知识点:排序
描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )

数据范围: 1≤n≤2×10^9 + 14
输入描述:
输入一个整数
输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。

示例1
输入:180
输出:2 2 3 3 5
解析:sqrt
什么是质数因子
“质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
代码

                                     /*方法1*/
#include <stdio.h>
#include <math.h>

int main(void)
{
    int a,b,i=0;
    scanf("%d",&a);
    for(b=2;b<=a;b++){      /*最小质数因子必小于输入数字的平方根*/
        if(b>(sqrt(a)+1)){
            b =a;
        }
        while(a%b==0){
            printf("%d ",b);
            a = a/b;
        }
    }
    printf("\n");
    return 0;
}
-------------------------结果------------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test 
180
2 2 3 3 5 
song@song-virtual-machine:~/C_Program/interview_code$ 

HJ37 统计每个月兔子的总数

知识点:查找;排序
描述
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。
例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:输入满足1≤n≤31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
示例1
输入:3
输出:2
代码:
分析:

1、数组定义
dp[i]表示第i个月的兔子总数
2、数组元素关系式
dp[i]=dp[i-1]+dp[i-2]
3、初值
dp[1]=1
dp[2]=1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
    int mon;
    while(scanf("%d",&mon)!=EOF) {
        int *dp=(int *)malloc((mon+1)*sizeof(int));    /*创建一个数组用于保存历史数据*/
        dp[1]=dp[2]=1;      /*赋初值*/
        for(int i=3;i<=mon;i++) {   /*根据元素关系式求dp[mon]*/
            dp[i]=dp[i-1]+dp[i-2];
        }
        printf("%d\r\n",dp[mon]);
        free(dp);
    }
    return 0;
}

HJ51 输出单向链表中倒数第k个结点

知识点:链表;双指针
描述
输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第1个结点为链表的尾指针。
链表结点定义如下:

struct ListNode
{
    int m_nKey;
    ListNode* m_pNext;
};
正常返回倒数第k个结点指针,异常返回空指针.

要求:
(1)正序构建链表;
(2)构建后要忘记链表长度。
数据范围:链表长度满足1≤n≤1000,k≤n,链表中数据满足0≤val≤10000
本题有多组样例输入。
输入描述
输入说明
1、输入链表结点个数
2、输入链表的值
3、输入k的值
输出描述:
输出一个整数
示例1

输入:
8
1 2 3 4 5 6 7 8
4
输出:5

代码:
输出第k个节点

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//注意链表的定义语句 
//next处要用struct ListNode*因为ListNode方法还没有定义
//链表的写入 head tail  used三个指针;
typedef struct ListNode {
    int m_nKey; 
    struct ListNode* m_pNext;
}ListNode;   
int main(void)
{
    int n;  /*链表的个数*/
    while(scanf("%d",&n) !=EOF){
        ListNode *num,*head,*tail;  /*结点,头,尾*/
        /* 建立链表 */
        head =(ListNode *)malloc(sizeof(ListNode));
        head->m_pNext = NULL;

        tail=head;
        for(int i=0;i<n;i++){
            num=(ListNode *)malloc(sizeof(ListNode));
            scanf("%d",&num->m_nKey); 
            num->m_pNext =NULL;

            tail->m_pNext = num;
            tail=num;
        }
        head=head->m_pNext;

        /*打印链表*/
        ListNode *p=head;
        while(p!=NULL){
            printf("%d  ",p->m_nKey);
            p=p->m_pNext;
        }     
        printf("\n");

        /*查找链表第k个结点*/
        int search;
        scanf("%d",&search);
        if(search<=0||search>n){
            printf("0\n");
        }else{
            ListNode *find;
            find=head;
            for(int i=1;i<search;i++){
                find=find->m_pNext;
            }
            printf("%d\n",find->m_nKey);
        }
        free(head);
    }
    return 0;
}

----------------------------结果---------------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
8
2 7 6 3 9 12 12 8
2  7  6  3  9  12  12  8  
8
8
^C
song@song-virtual-machine:~/C_Program/interview_code$ 

方法1:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//注意链表的定义语句 
//next处要用struct ListNode*因为ListNode方法还没有定义
//链表的写入 head tail  used三个指针;
typedef struct ListNode {
    int m_nKey; 
    struct ListNode* m_pNext;
}ListNode;   
int main(void)
{
    int n;  /*链表的个数*/
    while(scanf("%d",&n) !=EOF){
        ListNode *num,*head,*tail;  /*结点,头,尾*/
        /*1, 建立链表 */
        head =(ListNode *)malloc(sizeof(ListNode));
        head->m_pNext = NULL;

        tail=head;
        for(int i=0;i<n;i++){
            num=(ListNode *)malloc(sizeof(ListNode));
            scanf("%d",&num->m_nKey); 
            num->m_pNext =NULL;

            tail->m_pNext = num;
            tail=num;
        }
        head=head->m_pNext;

        /*打印链表*/
        ListNode *p=head;
        while(p!=NULL){
            printf("%d  ",p->m_nKey);
            p=p->m_pNext;
        }     
        printf("\n");

        /*2,查找链表倒数第k个结点*/
        int search;
        scanf("%d",&search);
        if(search<=0||search>n){
            printf("0\n");
        }else{
            ListNode *find;
            find=head;
            for(int i=0;i<n-search;i++){
                find=find->m_pNext;
            }
            printf("%d\n",find->m_nKey);
        }
        free(head);
    }
    return 0;
}
----------------------------结果---------------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
8
1 2 3 4 5 6 7 8
1  2  3  4  5  6  7  8  
4
5
^C
song@song-virtual-machine:~/C_Program/interview_code$

HJ22 汽水瓶

知识点:数学;模拟
描述
某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。
小张手上有n个空汽水瓶,她想知道自己最多可以喝到多少瓶汽水。
数据范围:输入的正整数满足1≤n≤100
注意:本题存在多组输入。输入的 0 表示输入结束,并不用输出结果。
输入描述:
输入文件最多包含 10 组测试数据,每个数据占一行,仅包含一个正整数 n( 1<=n<=100 ),表示小张手上的空汽水瓶数。n=0 表示输入结束,你的程序不应当处理这一行。
输出描述:
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。
示例1

输入:
3
10
81
0
输出:
1
5
40

说明:
样例 1 解释:用三个空瓶换一瓶汽水,剩一个空瓶无法继续交换
样例 2 解释:用九个空瓶换三瓶汽水,剩四个空瓶再用三个空瓶换一瓶汽水,剩两个空瓶,向老板借一瓶汽水喝完得三个空瓶换一瓶汽水还给老板
方法1:
解析
题目描述中有讲到:剩2个空瓶子时,可以先找老板借一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。也就是说2个空瓶子即可换一瓶汽水喝,而且喝完之后手里也没有空瓶子。求解时直接把空瓶数除以2,即可得到正解。
代码

#include <stdio.h>
int main(void)
{
    int buf[10],i,nums;
    int *ptr = buf;
    for(i=0;i<10;i++){
        scanf("%d",&buf[i]);
        if(buf[i]==0){
            break;
        }
    }
    nums=i;     /*一共输入可5组数*/
    for(i=0;i<nums;i++){
        printf("%d\r\n",buf[i]/2);
    }
}

方法2:
解析:
并不是所有的问题都能用递归解决。要使用递归就必须要具备两个条件。
递归的思想是:为了解决当前问题 F(n),就需要解决问题 F(n–1),而 F(n–1) 的解决依赖于 F(n–2) 的解决……就这样逐层分解,分解成很多相似的小事件,当最小的事件解决完之后,就能解决高层次的事件。这种“逐层分解,逐层合并”的方式就构成了递归的思想。
使用递归最主要的是要找到递归的出口和递归的方式。所以递归通常分为两部分:递归的方式和递归的终止条件(最小事件的解)。这两个部分是递归的关键!
递归的方式,就是指递归公式,即对问题的分解,同时也是向递归终止条件收敛的规则。而递归的终止条件通常就是得出的最小事件的解。递归终止条件的作用就是不让递归无限地进行下去,最后必须要能“停”下来。
综上所述,使用递归必须要满足的两个条件就是:

  1. 要有递归公式。
  2. 要有终止条件。
    代码:
        /*方法1*/
#include <stdio.h>
int bottle(int num)
{
    int x=0,y=0;
    int res=0;

    if(num==1){
        return 0;
    }else if(num==2){
        return 1;
    }else{
        x=num%3;
        y=num/3;
        res=y;
        res=res+bottle(x+y);
        return res;
    }
}
int main(void)
{
    int buf[10],i,nums;
    int *ptr = buf;
    for(i=0;i<10;i++){
        scanf("%d",&buf[i]);
        if(buf[i]==0){
            break;
        }
    }
    nums=i;     /*一共输入可5组数*/
    for(i=0;i<nums;i++){
        printf("%d\r\n",bottle(buf[i]));
    }
}
--------------------结果-------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test 
3
10
81
0
1
5
40
song@song-virtual-machine:~/C_Program/interview_code$ 

HJ61 放苹果

知识点:递归;动态规划
描述
把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?
注意:如果有7个苹果和3个盘子,(5,1,1)和(1,5,1)被视为是同一种分法。
数据范围:0≤m≤10 , 1≤n≤10 。
输入描述:
输入两个int整数
输出描述:
输出结果,int型
示例1
输入:7 3
输出:8
方法1:动态规划
解析:

1、数组定义
	dp[m][n]: 把m个苹果放在n个盘子有dp[m][n]中放法
2、数组元素关系式
这里有两种情况,
	1)当苹果数小于盘子数时
	也就是m<n,与m个苹果m个盘子的放法是一样的,也就是m<n,dp[m][n]=dp[m][m]

	2)当苹果数大于等于盘子数的时候,也就是m>=n,不同的放法可以分成两类:
		a、有至少一个盘子空着,原则上相当于dp(m,n) =dp (m,n-1) + dp (m,n-2) + dp (m,n-3)... 但是考虑到dp (m,n-2)包含在dp (m,n-1)中(这里思考下!),避免重复统计,则dp (m,n) = dp (m,n-1)
		b、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即dp(m,n) = dp(m-n,n).
		则总的放苹果的放法数目等于两者的和,即 dp(m,n) =dp(m,n-1)+dp(m-n,n)
3、初值
当有一个苹果或者没有苹果,不管有多少篮子,只有一种放法:dp[0][j]=1;dp[1][j]=1;
当有一个篮子或者没有篮子,不管有多少苹果,只有一种放法:dp[i][0]=1; dp[i][1]=1;

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
int main(void)
{
    int m,n;
    while(scanf("%d %d",&m,&n)!=EOF){
        int **dp=(int **)malloc((m+1)*sizeof(int *));       /*定义存储历史数据的数组*/
        for(int i=0;i<m+1;i++){
            dp[i]=(int *)malloc((n+1)*sizeof(int));
            memset(dp[i],0,(n+1)*sizeof(int));
        }
        for(int i=0;i<m+1;i++){
            dp[i][0]=1;     /*当篮子为0个时,不管苹果有多少,都只有一种方法*/
            dp[i][1]=1;     /*当篮子为1个时,不管苹果有多少,都只有一种方法*/
        }
        for(int i=0;i<n+1;i++){
            dp[0][i]=1;     /*当苹果为0个时,不管篮子有多少,都只有一种方法*/
            dp[1][i]=1;     /*当苹果为1个时,不管篮子有多少,都只有一种方法*/
        }
        for(int i=0;i<m+1;i++){
            for(int j=0;j<n+1;j++){
                printf("%d  ",dp[i][j]);
            }
            printf("\n");
        }   
        printf("-----------------------------------------\r\n");
        for(int i=2;i<m+1;i++){
            for(int j=2;j<n+1;j++){
                if(i<j){
                    dp[i][j]=dp[i][i];
                }else{
                    dp[i][j]=dp[i-j][j]+dp[i][j-1];       
                }
            }
        }
        for(int i=0;i<m+1;i++){
            for(int j=0;j<n+1;j++){
                printf("%d  ",dp[i][j]);
            }
            printf("\n");
        }   
        printf("-----------------------------------------\r\n");
        printf("%d\r\n",dp[m][n]);
        for(int i=0;i<m+1;i++){
            free(dp[i]);
        }
        free(dp);
    }
}

方法2:递归

解析

设f(m,n)为m个苹果,n个盘子的放法数目,则先对n作讨论,
		当m<n:必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响,即if(n>m) f(m,n) = f(m,m) 问题变成m个苹果,m个盘子的问题。也就是下面的m>=n的情况

当m>=n:不同的放法可以分成两类:
		1、有至少一个盘子空着,原则上相当于f(m,n) = f(m,n-1) + f(m,n-2) + f(m,n-3)... 但是考虑到f(m,n-2)包含在f(m,n-1)中(这里思考下!),避免重复统计,则f(m,n) = f(m,n-1)
		2、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即f(m,n) = f(m-n,n).
		则总的放苹果的放法数目等于两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n)
		递归出口条件说明: 当n=1时,所有苹果都必须放在一个盘子里,所以返回1; 当m=0时,没有苹果可以放置,返回1种放法; 递归的两条路,第一条n会逐渐减少,终会到达出口n==1; 第二条m会逐渐减少,因为n>m时,我们会return f(m,m) 所以终会到达出口m==0

代码:

        /*方法2*/
#include <stdio.h>

/* 设f(m,n)为m个苹果,n个盘子的放法数目, */
int fun(int m,int n){
    if(m==0||n==1){
        return 1;
    }else if(m<n){
        return fun(m,m);
    }else{
        return fun(m-n,n)+fun(m,n-1);/*没有空盘子的情况+有空盘的情况*/
    }
}
int main(){
    int a,b,num;
    while(~scanf("%d%d",&a,&b)){
        num = fun(a,b);
        printf("%d\n",num);
    }
}
------------------------------结果-----------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
7 3
8
^C
song@song-virtual-machine:~/C_Program/interview_code$

HJ8 合并表记录

知识点:哈希
描述
数据表记录包含表索引index和数值value(int范围的正整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照index值升序进行输出。
提示:
0 <= index <= 11111111
1 <= value <= 100000
输入描述:
先输入键值对的个数n(1 <= n <= 500)
接下来n行每行输入成对的index和value值,以空格隔开

输出描述:
输出合并后的键值对(多行)
示例1

输入:
4
0 1
0 2
1 2
3 4
输出:
0 3
1 2
3 4

示例2

输入:
3
0 1
0 2
8 9
输出:
0 3
8 9
        /*方法1*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
typedef struct datalist
{
    int index;
    int value;
}datalist;
int main(void)
{
    int n;
    while(scanf("%d", &n) != EOF) {
        datalist *list=(datalist*)malloc(n*sizeof(datalist));
        int max_index=0;
        for(int i=0; i<n; i++){
            scanf("%d",&list[i].index);
            scanf("%d",&list[i].value);
            if(list[i].index>max_index){
                max_index = list[i].index;
            }
        }
        int *buf=(int *)malloc(max_index*sizeof(int));
        memset(buf,0,max_index*sizeof(int));

        for(int i=0; i<n; i++){
            buf[list[i].index] +=list[i].value;
        }
        for(int i=0; i<=max_index; i++) {
            if(buf[i]){
                printf("%d %d\n", i, buf[i]);
            }
        }
        free(buf);
        free(list);
    }
}
        /*方法2*/
#include<stdio.h>
#include <malloc.h>
#include <string.h>

typedef struct STU{
    int index;
    int value;
}STU;

int main(void) 
{
    int n;   /*表示数量*/
    while (scanf("%d", &n) != EOF){  
        STU *group=(STU *)malloc(n*sizeof(STU));
        for(int i=0; i<n; i++){
            scanf("%d %d",&(group[i].index),&(group[i].value));
        }
        int m=0;
        int sum=0;
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                if(group[i].index == group[j].index){
                    sum=sum+group[j].value;
                }
            }
            group[i].value=sum;
            sum=0;
        }
        printf("---------------------------------------\n");
        for(int i=0; i<n; i++){
            printf("%d %d\n",group[i].index,group[i].value);
        }
        /*冒泡排序*/
        int temp_index = 0;
        int temp_value = 0;
        for(int i=0; i<n-1; i++){
            for(int j=0; j<n-i-1; j++){
                if(group[j].index>group[j+1].index){
                    temp_index=group[j].index;
                    temp_value=group[j].value;
                    group[j].index=group[j+1].index;
                    group[j].value=group[j+1].value;
                    group[j+1].index=temp_index;
                    group[j+1].value=temp_value;
                }
            }
        }
        printf("---------------------------------------\n");
        for(int i=0; i<n; i++){
            printf("%d %d\n",group[i].index,group[i].value);
        }
        printf("---------------------------------------\n");
        int last = group[0].index;
        printf("%d %d\n",group[0].index,group[0].value);
        for(int i=1; i<n;i++){
            if(group[i].index!=last){
              printf("%d %d\n",group[i].index,group[i].value);
            }
            last = group[i].index;
        }
        free(group);

    } 
    return 0;
}
----------------------------结果---------------------------------
song@song-virtual-machine:~/C_Program/interview_code$ ./test
4
1 5
0 1
0 6
2 7
---------------------------------------
1 5
0 7
0 13
2 7
---------------------------------------
0 7
0 13
1 5
2 7
---------------------------------------
0 7
1 5
2 7
^C
song@song-virtual-machine:~/C_Program/interview_code$ 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

华为机试--简单题(一) 的相关文章

  • rke2 在线部署 kubernetes

    文章目录 1 还原虚拟机 2 背景 3 介绍 4 预备条件 5 1 配置网卡 5 配置主机名 6 配置互信 7 安装 ansible 8 系统初始化 9 kube master01 部署 9 1 定制配置文件 可选 9 2 部署 9 3 命
  • 微信二维码的生成(java后端)--邀请新人

    目录 写在前言 1 微信官方文档 2 具体分析 写在前言 最近因为在学习微信小程序邀请新用户的功能 所以需要后端生成二维码并且携带本人的用户id或者其他的信息 传给前端 用户通过这个二维码去进行登录或者其他的操作 这时候前端人员记录下来邀请

随机推荐

  • Qt 2D绘图坐标系统

    一 坐标系简介 Qt中每一个窗口都有一个坐标系 默认的 窗口左上角为坐标原点 然后水平向右依次增大 水平向左依次减小 垂直向下依次增大 垂直向上依次减小 原点即为 0 0 点 然后以像素为单位增减 例如 void Dialog paintE
  • Qt之QGraphicsView实战篇

    作者 billy 版权声明 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 前言 前面的章节介绍了 Graphics View 绘图架构 终于到实战了 真的是千呼万唤始出来 这一章节就用 Graphics View 绘图
  • 第二章:Matplotlib之艺术画笔见乾坤

    第二章 艺术画笔见乾坤 一 概述 1 matplotlib的三层api matplotlib的原理或者说基础逻辑是 用Artist对象在画布 canvas 上绘制 Render 图形 就和人作画的步骤类似 准备一块画布或画纸 准备好颜料 画
  • Tomcat重启单个服务

    一个tomcat中有多个服务 每次为了重启某个服务 需要重新启动Tomcat 会影响其他服务的正常运行 可通过以下方式进行设置 进入Tomcat服务管理页面 对单个服务进行管理 1 首先我们启动tomcat 访问主页 可以看到右上位置有三个
  • MYSQL--基础--10--慢查询日志

    MYSQL 基础 10 慢查询日志 1 是什么 是MySQL提供的一种日志记录 支持将日志记录写入文件 将SQL查询时间超过 大于 设置阈值的语句 记录到慢查询日志中 2 查看语句 2 1 慢日志是否开启和日志文件位置 show varia
  • 【yolo】yolov5-seg实例分割标签

    文章目录 前言 yolo标签 yolov5 seg标签 转换代码 前言 不同于以往的yolo数据 用的是目标框的label 再加上语义标签 yolov5 seg中用的标签只有一个语义标签 没有目标框的标签 具体对比如下 yolo标签 1 目
  • java 获取月份 几周_java – 我想在特定的月份获得几周的时间

    Calendar类的WEEK OF YEAR属性可能对您有用 参考 Calendar class 创建一个新的日期 将是一个月的第一天 得到这一天的一周的这个星期 让你说起点价值 创建一个新的日期 这将是给定月份的最后一天 获得今年的一周
  • FastCFS核心组件FastStore架构及特点

    FastCFS核心组件FastStore架构及特点 本篇文章转载于 FastCFS 作者 余庆 大佬的 FastDFS分享与交流 公众号 上一篇文章介绍了 FastCFS 服务端两大核心组件 FastDIR 和 FastStore 其中 F
  • python文本数据处理_Python文本数据分析与处理

    Python文本数据分析与处理 新闻摘要 分词 使用jieba分词 注意lcut只接受字符串 过滤停用词 TF IDF得到摘要信息或者使用LDA主题模型 TF IDF有两种 jieba analyse extract tags conten
  • Linux中su、su -和sudo的区别

    su 切换到root用户 但是并没有转到root用户家目录下 即没有改变用户的环境 su 切换到root用户 并转到root用户的家目录下 即改变到了root用户的环境 这个涉及到不同用户下的环境变量的配置 sudo 通过sudo 我们能把
  • 【C++】迭代器

    目录 1 迭代器 1 1 迭代器的操作 1 2 迭代器范围 1 3 使用左闭合范围蕴含的编程假定 2 begin和end成员 3 容器操作可能使迭代器失效 3 1 迭代器失效 3 2 编写改变容器的循环程序 3 3 不要保存end返回的迭代
  • (1)分类算法

    分类算法原理 一 KNN K 近邻 1 定义 如果待推测点 空心点 在中间的某个位置 则计算出与其最邻近的4个样本点 K 4 而此时这4个样本点包含了3个类别 1红 1蓝 2绿 针对这样的情况 knn算法通常采用投票法来进行类别推测 即找出
  • 安装VMware Tools方法(对于 18.04LTS版本)

    大家都知道 每一种虚拟机 如VMware Parallels Desktop等都有一个Tools用来让linux系统和windows系统可以共用剪贴板等工具 使得在windows上复制了的东西 在linux ubuntu 上可以访问 对于V
  • MQ知识梳理

    常见MQ有哪几种 分别适用什么场景 常见的有ActiveMQ RabbitMQ RocketMQ Kafka ActiveMQ比较成熟 功能多 但也比较老 各方面都不突出 目前已很少使用 RabbitMQ性能高 功能多 吞度量万级 有开源活
  • C#中的接口(interface)

    接口的命名规范 I 名词 接口与抽象类的区别 接口是由抽象类演变而来的 抽象类是未完全实现逻辑的类 其内部可以有抽象成员 也可以有非抽象成员 且子类在覆写抽象成员时 需要修饰符override 而接口是完全未实现逻辑的 其内部只允许存在抽象
  • java报错:com.alibaba.druid.pool.DruidDataSource.info {dataSource-1} inited

    JDBC使用Druid连接池连接数据库的时候 遇到报错 com alibaba druid pool DruidDataSource info dataSource 1 inited 具体报错信息如下 从网页上报错信息 可以看到是获取驱动名
  • 彻底理解vue底层运用的核心函数Object.defineProperty

    一个函数诞生一个框架 vue就是得益于javaScrit的原生函数Object defineProperty而诞生的 那么Object defineProperty到底是什么 它的用法又是怎样的呢 很简单 它就是用来为对象定义属性的 从字面
  • 51单片机串口通信数码管显示

    外部晶振 11 0592MHZ 主控芯片 STC89C52 程序功能 串口工作方式1 8位UART 比特率9600 接收串口数据 数码管以十 进制格式显示 并且把接收到的数据加1后通过串口发出
  • 【Idea】创建包自动分层

    Idea 创建包自动分层 创建Maven 项目时 新建包使得Tomcat查找访问路径时更准确 但是有时包会不分层 如图1 然后我们使用图3的方法取消勾选 使得新建包时自动分层 如图2
  • 华为机试--简单题(一)

    HJ14 字符串排序 知识点 字符串 排序 描述 给定 n 个字符串 请对 n 个字符串按照字典序排列 数据范围 1 n 1000 字符串长度满足1 len 100 输入描述 输入第一行为一个正整数n 1 n 1000 下面n行为n个字符串