C语言编程题

2020.8.2

给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:
1.	1
2. 	11
3. 	21
4. 	1211
5. 	111221
char * countAndSay(int n)
{
	char *res = (char*)malloc(sizeof(char) * 5000);
	char *tmp = (char*)malloc(sizeof(char) * 5000);
	res[0] = '1'; res[1] = '\0';     // res 初始化为 "1"
	int len = 1;                     // len 为 res 的有效长度
	while (--n) 
	{
		int i = 0, j = 0;
		while(i < len)
		{
			int count = 1;
			char c = res[i++];
			while (i < len && res[i] == c)    // 计算本轮报数结果,即本轮有几个 c
			{
				i++;
				count++;
			}
			tmp[j++] = count + '0';           // 将报数结果存入 tmp
			tmp[j++] = c;
		}
		tmp[j] = '\0';
		strcpy(res, tmp);                     // 将 tmp 复制到 res,并更新 res 长度
		len = j;
	}
	 return res;
}

2020.7.30
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

采用递归算法


//Definition for singly-linked list.
struct ListNode {
	int val;
	struct ListNode *next;
}

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
    if(l1==NULL)
        return l2;
    if(l2==NULL)
        return l1;
    if(l1->val < l2->val){
        l1->next = mergeTwoLists(l1->next,l2);
        return l1;
    }else{
        l2->next = mergeTwoLists(l1,l2->next);
        return l2;
    }
}

我自己的咸鱼算法

//Definition for singly-linked list.
struct ListNode {
	int val;
	struct ListNode *next;
}


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	struct ListNode h;
	struct ListNode* p=(&h);
	while((l1)&&(l2))
	{
		 if((l1->val)<(l2->val))
		 {
			p->next=l1;
			p=l1;
			l1=l1->next;
		 }
		 else
		 {
			p->next=l2;
			p=l2;
			l2=l2->next;
		 }
		 if(l1)
		 	p->next=l1;
		 else
		 	p->next=l2;
		 
		 return (h.next);
	}
	

2020.7.11
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

  1 #include"stdio.h"
  2 #include"math.h"
  3 #define total_num 4
  4 #define des_num   3
  5 int main()
  6 {
  7         int a[total_num]={1,2,3,4};
  8         int i,j,k;
  9         for(i=0;i<total_num;i++)
 10         {
 11                 for(j=0;j<total_num;j++)
 12                 {
 13                         if(!(j-i))
 14                                 continue;
 15                         for(k=0;k<total_num;k++)
 16                         {
 17                                 if(!((k-i)&&(k-j)))
 18                                         continue;
 19                                 printf("%d\n",(int)(a[i]*pow(10,des_num-1)+a[j]*pow(10,des_num-2)+a[k]*pow(10,des_num-3)));
 20                         //      printf("%d%d%d\n",a[i],a[j],a[k]);
 21                         }
 22                 }
 23         }
 24         return 0;
 25 }

其中用到的 double pow(double x,double y)函数,要包含头文件math.h。由于其返回值是double型,在gcc中若不加强制类型转换(int)而用“%d”输出,得不到正确的结果。
要求i,j,k这三个数不相等,一开始我在两个if的条件中均忘记加感叹号来取反,导致判断的条件为如果不相等,则跳过此轮循环,直接进入下一轮循环。

  • %p和%x的区别
    %p 中的 p 是 pointer 的缩写,16进制输出,并且会自动附加前缀 0x。用来打印地址
    %x 则是单纯地以16 进制的形式来打印数据
    按理来说。64位的系统,指针也应该是64位二进制数,而在我下面的 code 中只输出了48位。这是因为目前 x86_64 处理器硬件限制导致。x86_64 处理器的地址线只有48条,因此规定硬件传入的地址从0 - 47 就是处理器的实际寻址能力;地址线上剩余的16位即 48 - 63 位地址线的数值必须与 第47位上的数值保持一致。47位上的地址线要么是0,要么是1,两种情况。所以合法的地址也分为两部分。第一部分 :47位是0----->范围是 0 - 0x0000 7fff ffff ffff;第二部分:47位是1----->范围是 0xffff 8000 0000 0000 - 0xffff ffff ffff ffff。一般来说我们是看不到高段地址的,如果你的机器的内存大于 128TB,可以看见高段地址。
    打印指针用 %p 才是正确的选择。
#include"stdio.h"
int main()
{
 int a;
 printf("The length of a pointer is %d.\n",sizeof(int *));
 printf("%%p %p\n",&a);
 printf("%%x %x\n",&a);
 printf("%%lx %lx\n",&a);
 return 0;
}

输出为

he length of a pointer is 8.
%p 0x7ffdd360af74
%x d360af74
%lx 7ffdd360af74
  • C 语言标准库里的头文件用 < >,自定义的头文件用 “ ”
  • C 语言中,使用指针来访问某一单元的数据比使用数组下标来访问的速度快。
  • sizeof函数返回的是 long int 型,所以用 %ld,最好不要用 %d 。
  • 使用 INT_MIN 和 INT_MAX 这两个宏的头文件为 limits.h,
    拿单字节整数来说,无符号型,其表示范围是[0,255],总共表示了256个数据。有符号型,其表示范围是[-128,127]。
    先看无符号,0表示为0000 0000,255表示为1111 1111,刚好满足了要求,可以表示256个数据。
    再看有符号的,若是用原码表示,0表示为0000 000。因为咱们有符号,所以应该也有个负0(虽然它还是0):1000 0000。
     那我们看看这样还能够满足我们的要求,表示256个数据么?
     正数,没问题,127是0111 1111,1是0000 0001,当然其它的应该也没有问题。
     负数呢,-1是1000 0001,那么把负号去掉,最大的数是111 1111,也就是127,所以负数中最小能表示的数据是-127。
     如果我们把其中的一个0指定为-128,是不行的:一是它与-127的跨度过大;二是在用硬件进行运算时不方便。所以,计算机中,负数是采用补码表示。
     单字节-1,原码为1000 0001,反码为1111 1110,补码为1111 1111,计算机中的单字节-1就表示为1111 1111。单字节-127,原码是1111 1111,反码1000 0000,补码是1000 0001,计算机中单字节-127表示为1000 0001。单字节-128,原码貌似表示不出来,除了符号为,最大的数只能是127了,其在计算机中的表示为1000 0000。
     也可以从数据大小上来理解。还是以单字节数据为例。有符号数中,正数的范围是[1,127],最大的是127,不考虑符号为,其表示为111 1111;最小的是1,不考虑符号位,其表示为000 0001。
     负数中,最大的是-1,就用1111 1111表示。后面的数据依次减1。减到1000 0001的时候,我们用它标示了-127。再减去1,就变成1000 0000了,用它表示-128,刚好可以满足表示范围。
  • 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
int reverse(int x)
{ 
   long y = 0;   
    while(x)    
    {       
      y *= 10;       
      y += x%10;       
      x /= 10;     
     }    
     if(y > (int)(0x7fffffff) || y < (int)(0x80000000))        
     return 0;    
     else         
     return (int)y;
 }

这里的 0x7fff ffff 和 0x8000 0000 分别表示最大值和最小值 ,如果不加上 int 来强制类型转换,就会默认是 long 型(与 y 一样来比较大小),此时 0x80000000 不再是一个负数。

  • double型,float型的数据用 %d输出会是乱码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值