C语言经典编程题

一、递归求一个数的阶乘:

int factorial(int n)
{
    while (n > 1)
    {
        return n*func(n-1);
    }
}

当然也可以不用while循环,因为都是n级运算,算法复杂度都为O(n),所以影响不大。

int factorial(int n)
{
    if(n == 0)
    {
        return 1;
    }
    else 
    {
        return n*func(n-1);
    }
}

二、输入一个整数(任意位数),倒叙输出:

因为要把一个整数颠倒过来。所以得把从低位到高位的顺序分别打印出来,然后乘以相应的倍数,最后相加即可。

#include <stdio.h>

int getLen(int num)    //计算该数一共有多少位(长度)
{
    int flags = 0;
    for (num; num >0 ; num/=10)  
    {
        flags++;   
    }
    return flags;   //返回位数(长度)
}

int getIndex(int len)   //len是数的位数
{
    int i=0;
    int res = 1;
    for (i = 0; i < len ; i++)
    {
        res=res*10;    
    }
    return res;    //返回10^i
}

int main()
{
    int num,temp,LastNum;
    printf("please input a num:\n");
    scanf("%d",&num);

    int len = getLen(num);

    int i=0;   
    for(i = 0; i<len ; i++)
    {

        temp=num%10;   //提取每个位的数
        num=num/10;

        LastNum+=temp*getIndex(len-i-1);   //这里是个累加过程
    }

    printf("the resault=%d\n",LastNum);
}

三、将一个数组逆序放到原来数组中。(考虑复杂度)

算法一:相当于把数组对应位置前后调换,只需要n/2次。

for (i = 0;i < n/2;i++)
{
    t = arr[i];
    arr[i] = arr[n-1-i];
    arr[n-1-i] = t;
}

算法二:

for (i = 0;i < n;i++)
    b[i] = a[n-i-1];
for (i = 0;i < n;i++)
    a[i]=b[i];

算法一借助辅助空间t ,而算法二借助辅助空间为 b[n]。所以空间复杂度来说,算法一空间复杂度为O(1),算法二空间复杂度为O(n)。


四、斐波那契数列:

Fib(0) = 0
Fib(1) = 1
Fib(n) = Fib(n-1) + Fib(n-2)

F() = 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 …

int Fibonacci(int n)
{
    if (n <= 1)
        return n;
    else
       return Fibonacci(n - 1) + Fibonacci(n - 2);
}

这里,给定规模 n,计算 Fib(n) 所需的时间为计算 Fib(n-1) 的时间和计算 Fib(n-2) 的时间的和。

T(n<=1) = O(1)

T(n) = T(n-1) + T(n-2) + O(1)

                 fib(5)   
             /             \     
       fib(4)                fib(3)   
     /      \                /     \
 fib(3)      fib(2)         fib(2)    fib(1)
/     \        /    \       /    \  

通过使用递归树的结构描述可知算法复杂度为 O(2n)。

int Fibonacci(int n)
{
    if (n <= 1)
        return n;
    else
    {
        int[] f = new int[n + 1];
        f[0] = 0;
        f[1] = 1;

        for (int i = 2; i <= n; i++)
        {
            f[i] = f[i - 1] + f[i - 2];
        }

        return f[n];
   }
}

不使用递归:(复杂度降为O(n))

int Fibonacci(int n)
{
   if (n <= 1)
        return n;
   else
   {
        int iter1 = 0;
        int iter2 = 1;
        int f = 0;

        for (int i = 2; i <= n; i++)
        {
            f = iter1 + iter2;
            iter1 = iter2;
            iter2 = f;
        }

        return f;
     }
}

五、判断是大端还是小端字节序:

这里写图片描述

方法一(使用联合体):
这里用到了联合体:联合体内成员共享内存,所以所有成员首地址相同。
所以可以通过对较长的成员赋值,通过判断另个一个成员变量的值来判断存放的是高位字节还是低位。

union
    {
        char             c;
        unsigned short   s;    
    }A;

    A.s = 0x1234;         
    if(A.c == 0x12)   //0x12是高位字节
    {
        printf("It's MSB");    // 1  0x34
                               // 0  0x12
    }
    else
    {
        printf("It's LSB");    // 1  0x12
                               // 0  0x34
    }

方法二:(不使用联合)

    unsigned int a = 0x12345678;
    unsigned char i = (unsigned char)a;   //截断a

    if (i == 0x12)
    {
        printf("MSB");
    }
    else
    {
        printf("LSB");
    }

六、桶排序:对公司员工年龄进行排序(存在年龄相同情况)

这里用的是桶排序的思想。桶排序虽然速度快,算法简单,但是因为要借助辅助空间,浪费空间,只适合对较少的数据排序。

#include <stdio.h>
void sortage(int arr[],int len)
{
    int i=0;
    if (arr == NULL || len <= 0)
    {
        return;
    }

    const int oldestAge = 99;     //最大年龄
    int timeofAge[oldestAge+1];   //每个年龄次数(辅助内存)

    //初始化数组
    for(i = 0;i <= oldestAge;i++)
    {
        timeofAge[i] = 0;
    }

    for (i = 0;i < len;i++)  //循环读入年龄
    {
        int age = arr[i];   
        if(age < 0 || age > oldestAge )
        {
            printf("age is not in the range");
        }
        timeofAge[age]++;  //每个年龄作为数组的下标,就代表这个年龄的员工有几人
    }

    int index=0;
    int j=0;
    //双层循环,外层遍历所有年龄
    for (i = 0;i <= oldestAge;i++)
    {
        for (j = 0;j < timeofAge[i];j++) //内层循环:出现几次就打印几次
        {
            arr[index] = i;
            ++index;
        }
    }

}
void main()
{
    int i=0;
    int arr[7]={22,18,23,22,50,34,19};
    sortage(arr,7);
    for(i = 0;i < 7;i++)
    {
        printf("%d ",arr[i]);
    }
}

七、字符串移动:

编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh” 函数头是这样的:

//pStr是指向以’\0’结尾的字符串的指针

//steps是要求移动的n

void LoopMove ( char * pStr, int steps )

{

//请填充…

}

正确答案:
解析:都是用临时变量来存储,然后通过指针指向来实现改变。解答2更直观。

正确解答1void LoopMove ( char *pStr, int steps )
{
    int n = strlen( pStr ) - steps;
    char tmp[MAX_LEN];
    strcpy ( tmp, pStr + n );
    strcpy ( tmp + steps, pStr);
    *( tmp + strlen ( pStr ) ) = '\0';
    strcpy( pStr, tmp );
}

正确解答2void LoopMove ( char *pStr, int steps )
{
    int n = strlen( pStr ) - steps;
    char tmp[MAX_LEN];
    memcpy( tmp, pStr + n, steps );
    memcpy(pStr + steps, pStr, n );
    memcpy(pStr, tmp, steps );
}

八 、计算最后一个单词的长度

思想:这里采用逆向思维,把字符串从后往前数,依次对每个字符判断是否为空,定义一个变量计数。

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s;
    while(getline(cin,s))   //c++键盘输入的一种表达
    {
        int n=0,flag=1;
        for(int i = s.length()-1; i >= 0;--i)
        {//倒着计算
            if(flag && s[i]==' ')
            {
                //如果末尾有空格,先清除末尾空格
                continue;
            }
            else if(s[i]!=' ')
            {
                flag = 0;
                ++n;
            }
            else
            {
                break;
            }
        }
        cout << n << endl;
    }

    return 0;
}

九、联发科2017笔试题:

删除一个字符串中指定的所有某个字符。

解法一:
思想:找到某字符后把后面的字符串依次往前移动。算法复杂度为O(n^2)。

void dele_char(char *str,char s)
{
    char *p = str;
    char *temp=NULL;
    while ( *p != '\0' )
    {
        if (*p == s)
        {
            temp = p;  //找到字符后保存该地址,方便返回继续遍历
            while (*p != '\0' )
            {
                *p = *(p+1);
                p++;
            }
            p = temp-1; //返回前一个位置,为了防止该字符连续出现
        }

        p++;
    } 
}

方法二
思想:上面方法复杂度是O(n^2),下面用更简单的算法复杂度来实现。这里思想是直接对该字符不予理踩,对不相等的部分重新赋值

void dele_char(char *str,char s)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < strlen(a); i++)
    {
        if (a[i] != 'f')
        {
            a[j] = a[i];  //把不相等的部分进行赋值
            j++;
        }
    }
    a[j] = '\0';   //最后一位设置为'\0'

十、用一个表达式判断一个整数是否在某两个整数之间

a < b < c : 判断b在a~c之间

static inline int between(__u32 a, __u32 b, __u32 c)
{
    return c - a >= b - a;
}

杰发科技2015改错题:

把一个字符串s拷贝到t中,并且把倒叙的字符串s接到t后面。
如:
输入:abc.
打印:abccba

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

void inv_cat(char *s,char *t)
{
    int i,len;


    len = strlen(s);

    for (i=0; i<len; i++)
    {
         t[i] = s[i];
    }

     for (i=0; i<len; i++)
    {
        t[len+i] = s[len-1-i];  //原题这里少了-1
    }
    t[2*len] = '\0';  //原题为2*len-1
 }

 int main()
 {
     char s[100];
     //原题t没有分分配内存,直接段错误
     char *t =(char *)malloc(sizeof(char)); 

     printf("\nPlease enter string s:\n");
     scanf("%s",&s);
     inv_cat(s,t);
    printf("The result is : %s",t);
 }

持续更新中。。。。

  • 57
    点赞
  • 494
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值