大魔王程序员生成记#06.2#C语言习题

目录

 

13.第一个只出现一次的字符   "abacbd"

14."abcdef"==>cdefab   左旋数组

15.输出杨辉三角,10行

16.输出1-n^2的自然数构成的魔方阵

17.函数的返回值,是如何带出函数的?寄存器有关?

18.汉诺塔问题

19.在第一个字符串中,删除第二个字符串中的所有字符串中所有的字符

"welcome tulun"  "come"  ==》"wltulun"

20.定义一个结构体变量(包括年,月,日)。计算该日在本年中是第几天,注意闰年问题

21.筛选法求100以内的所有素数 

22.字符串相加Hello world! 102

23.括号匹配.({()})  “({)” 或者 “([{})]” 都不符合要求

24.求一个有序数组中两个值相加为k的数字,返回这两个数字的下标。

25.数组中前K个最小的数字 

 26.出现次数超过数组长度一半的数字,如:{1,2,3,2,2,2,5,4,2}

27.左数第 bit 位 置 1

28.左数第 bit 位置 0

29.获取第 bit 位的值

30.写一个函数,它从一个字符串中提取一个子字符串,返回值是存储在dst数组中的子字符串的长度

 31.从一个字符串中除去多于的空格

32.长度受限的字符串拷贝 

33.长度受限的字符串连接函数

34.长度受限的字符串比较

35.查找字符ch,在给定字符串出现的最后一次

36.字符串查找给定字符,第n次出现的位置

37.strlen()函数实现

38.strchr()函数实现

39.strstr()函数实现

40.单位矩阵3阶

41.将字符串中的空格替换为#25

42.将字符串中的字符'*'移到字符串的前面 如:"tu**lu**n**ba**by",处理后为:"********tulunbaby 

43.可变参数编程,求和.int sum(int count,..)

44.可变参数编程,多种输出.void Print(const char *str,...)

45.非常规方法比较两个数的大小

46.写一个函数返回bool值,来判断给定的字符串A和B(假设都是小写字母),是否是B中的字符都存在于A中,如果是返回true,否则返回false

47.LeetCode06:将一个给定的字符串根据给定的行数以从上往下,从左到右进行Z字形排列。

48.LeetCode30:与所有单词相关联的字串


13.第一个只出现一次的字符   "abacbd"

char FirstNotRepeate(char *str )
{
	char *pbegin=str;
	char *pend=str;
	int len=strlen(str);//计算字符串长度
	while(len!=0)//每个字符进行一次遍历
	{
		while(*pend!='\0')
		{
			if(pbegin==pend)//指向相同地址就略过,即两个指针指向同一个数时,pend就略过这个数
			{
				pend++;
			}
			if(*pbegin==*pend)//两个数字相同时,记录出现一次的指针向后移
			{
				pbegin++;
			}
			pend++;
		}
		pend=str;//重置
		len--;
	}
	return *pbegin;
}
int main()
{
	char str[]="abacbd";
	printf("%c\n",FirstNotRepeate(str));
	return 0;
}

14."abcdef"==>cdefab   左旋数组

char* Left_Arry(char *str,int num)
{
	assert(str!=NULL);
	char *p=str;
	int len=strlen(str);//计算字符串的长度
	int t=len-num;
	char str2[10]={};//创建一个用来保存需要移动的字符
	for(int i=0;i

解题思路:将需要转移的字符提出,将原数组前移,将转移出的字符补在原数组中。

15.输出杨辉三角,10行

void Job(int (*arr)[10],int row,int col)
{
	for(int i=0;i

16.输出1-n^2的自然数构成的魔方阵

/*
魔方阵满足的计算方法:
1.每一个数存放的位置是前一个数的行数减一,列数加一
2.上一个数行数为一,则下一个数行数为n
3.上一个数列数为n,则下一个数行数减一
4.位置有数或上一个数是第一行第n列,下一个数放在上一个数的下面
*/

void Job1(int (*arr)[3],int n)
{
	int row=n;
	int col=n;
	assert(n%2!=0);//n只能为奇数
	for(int i=0;in-1)//判断是否为第一行第n列
		{
			row=row+2;
			col=col-1;
		}
		if(row<0)//若为真,说明前一个数行数为1
		{
			row=n-1;
		}
		if(col>n-1)//若为真,说明前一个数列数为n
		{
			col=0;
		}
		if(arr[row][col]==0)//若为真,说明位置上无数
		{
			arr[row][col]=k;
		}
		else               //位置上有数,变为前一个数的下一行
		{
			row=row+2;
			col=col-1;
			arr[row][col]=k;
		}
	}
}

17.函数的返回值,是如何带出函数的?寄存器有关?

答:
<= 4字节 通过寄存器带出来
>4 <=8 字节 通过两个寄存器带出来
>8 字节 通过产生临时量,此时返回值太大,寄存器已经没有足够的内存存放它
临时量是什么时候产生的?临时量是怎么找到的?怎么给临时量赋值的?
答:在函数调用之前;在调用函数之前,将临时量地址入栈,最后通过将被调用函数的返回值拷贝给临时量,将函数返回值带出。
参数带默认值的函数:
如:int sum(int a,int b,int c = 10);
给默认值从右边的参数给,参数的默认值只能给一次。

18.汉诺塔问题

void Hanno(int n,char pos1,char pos2,char pos3)
{
	if(n==1)
	{
		printf("%c-->%c\n",pos1,pos3);//只有一个盘子时,只需要将A-->C
	}
	else
	{
		Hanno(n-1,pos1,pos3,pos2);     //A  借助C-->B
		printf("%c-->%c\n",pos1,pos3); //A-->B
		Hanno(n-1,pos2,pos1,pos3);     //B  借助A-->C
	}
}
int main()
{
	Hanno(3,'A','B','C');
	return 0;
}

19.在第一个字符串中,删除第二个字符串中的所有字符串中所有的字符

"welcome tulun"  "come"  ==》"wltulun"

char *Deletechars(char *st1,char *st2)
{
	assert(st1!=null||st2!=null);
	char *pb=st1;
	while(*st2!='\0')
	{
		while(*pb!='\0')
		{
			if(*st2==*pb)  //如果两个字母相同赋值为0
			{
				*pb='0';
			}
			pb++;
		}
		st2++;
		pb=st1;//重新初始化
	}
	return pb;
}
void show(char* st1)
{
	assert(st1!=0);
	while(*st1!='\0')
	{
		while(*st1=='0')//如果有为0的元素,略过
		{
			st1++;
		}
		printf("%c",*st1);
		st1++;
	}
	printf("\n");
}
int main()
{
	char st1[]="welcome tulun";
	char st2[]="come";
	DeleteChars(st1,st2);
	Show(st1);
	return 0;
}

20.定义一个结构体变量(包括年,月,日)。计算该日在本年中是第几天,注意闰年问题

struct Days
{
	int year;
	int month;
	int day;
};
void Job1(Days day)
{
	int sum=0;
	switch(day.month)
	{
	case 1:
		sum=day.day;
		break;
	case 2:
		sum=day.day+31;
		break;
	case 3:
		sum=day.day+59;
		break;
	case 4:
		sum=day.day+90;
		break;
	case 5:
		sum=day.day+120;
		break;
	case 6:
		sum=day.day+151;
		break;
	case 7:
		sum=day.day+181;
		break;
	case 8:
		sum=day.day+212;
		break;
	case 9:
		sum=day.day+243;
		break;
	case 10:
		sum=day.day+273;
		break;
	case 11:
		sum=day.day+304;
		break;
	case 12:
		sum=day.day+334;
		break;
	}
	if((day.year%4==0&&day.year%100!=0)||day.year%400==0)//闰年的判断方法,能被4整除不能被100整除;能被400整除
	{
		sum++;
	}
	printf("%d月%d日是%d年的第%d天\n",day.month,day.day,day.year,sum);
}
int main()
{
	Days d={2018,11,3};
	Job1(d);
	return 0;
}

21.筛选法求100以内的所有素数 

void Job1()
{
	int arr[101]={0};
	for(int i=0;i<100;i++)
	{
		arr[i]=i+1;
	}
	for(int j=3;j<100;j++)//从第三个元素,即4开始
	{
		for(int i=2;i

 1.如何打印"Blunder??!??"
答:printf("\"Blunder??!??\"");
2.\40的值是多少?\100,\x40,\x100,\0123,\x0123
答:\40: ;\100:@;\x40:@;\x100:"256"对字符来说太大;\0123:换行3;\x0123:"291"对字符来说太大

22.字符串相加Hello world! 102

void Job1()
{
	char arr[40];
	signed char checksum=-1;
	int i=0;
	printf("输入字符串:");
	gets(arr);
	while(arr[i]!='\0')
	{
		checksum+=arr[i];
		i++;
	}
	checksum+='\n';//回车
	printf("输出结果:%s  %d\n",arr,checksum);
}
int main()
{
	Job1();
	return 0;
}

23.括号匹配.({()})  “({)” 或者 “([{})]” 都不符合要求

int Job2(char *arr)
{
	int j=0;
	int i=0;
	char temp1[40];
	while(arr[i]!='\0')
	{
		if(arr[i]=='('||arr[i]=='{'||arr[i]=='[')//只要是左括号就写入
		{
			temp1[j]=arr[i];
			j++;
			i++;
			continue;
		}
		//第一次出现右括号,与他相邻的必然是他的左括号
		if(arr[i]==')')
		{
			j--;
			if(temp1[j]=='(')
			{
				i++;
			}
			else
			{
				return -1;
			}
		}
		if(arr[i]=='}')
		{
			j--;
			if(temp1[j]=='{')
			{
				i++;
			}
			else
			{
				return -1;
			}
		}
		if(arr[i]==']')
		{
			j--;
			if(temp1[j]=='[')
			{
				i++;
			}
			else
			{
				return -1;
			}
		}
	}
	return 1;
}
int main()
{
	char arr[]="{([()])()";
	if(Job2(arr)==1)
	{
		printf("ok\n");
	}
	else
	{
		printf("no\n");
	}
	return 0;
}

24.求一个有序数组中两个值相加为k的数字,返回这两个数字的下标。

void Job3(int *arr,int len,int key)
{
	int bgn=0;
	int end=len-1;
	for(int i=0;i

25.数组中前K个最小的数字 

int Job(int *arr,int low,int high)
{
	int tmp ;
	while(low < high)
	{
		while(arr[low] > arr[high] && low < high)
		{
			low++;
		}
		while(arr[low] < arr[high] && low < high)
		{
			high--;
		}
	}
	tmp = arr[low];
	return tmp;
}
int main()
{
	int arr[] = {14,5,9,21,11,3,7,19};
	int start = 0;
	int end = 6;//前k个
	int k = Job(arr,start,end-1);
	printf("数组中前%d个最小的数字为:%d\n",end,k);
	return 0;
}

 26.出现次数超过数组长度一半的数字,如:{1,2,3,2,2,2,5,4,2}

/*
方法一:
思路:一个数字出现的次数超过数组的一半长度,根据一次划分函数,在数组的中位数上一定是这个数。
*/

/*
方法一:
思路:一个数字出现的次数超过数组的一半长度,根据一次划分函数,在数组的中位数上一定是这个数。
*/
void Swap(int *arr,int low,int high)
{
	int tmp = arr[low];
	arr[low] = arr[high];
	arr[high] = tmp;
}
int Job1(int *arr,int low,int high,int len)
{
	srand((unsigned int)time(NULL));
	Swap(arr,low,rand()%(high-low)+low);//随机生成 基准

	int tmp = arr[low];
	while(low < high)
	{
		while(low < high &&  arr[high] >= tmp)
		{
			high--;
		}
		if(high < low)
		{
			break;
		}
		else
		{
			arr[low] =arr[high];
		}
		while(low < high && arr[low] <= tmp)
		{
			low++;
		}
		if(low > high )
		{
			break;
		}
		else
		{
			arr[high] = arr[low];
		}
	}
	arr[low] = tmp;
	return arr[(len)/2];
}
int main()
{
	int arr[] = {1,2,3,2,2,2,5,4,2};
	int len = sizeof(arr)/sizeof(arr[0]);

	int key = Job1(arr,0,len-1,len);//方法一
	printf("%d\n",key);

	return 0;
}

/*
方法二:(一个多于一半数组的数,出现次数比其他数的总和还要多)
思路:在遍历数组的过程中,保存两个值,一个是数组中数字,一个是出现次数。
当遍历到下一个数字时,如果这个数字跟之前保存的数字相同,则次数加1,如果不同,则次数减1。
如果次数为0,则保存下一个数字并把次数设置为1。
*/ 

/*
方法二:(一个多于一半数组的数,出现次数比其他数的总和还要多)
思路:在遍历数组的过程中,保存两个值,一个是数组中数字,一个是出现次数。
当遍历到下一个数字时,如果这个数字跟之前保存的数字相同,则次数加1,如果不同,则次数减1。
如果次数为0,则保存下一个数字并把次数设置为1。
*/

int Job3(int *arr,int len)
{
	int sum = 0;
	int top = 1;
	int *brr = (int *)malloc(sizeof(int)*2);
	brr[top] = arr[0];//brr的初始化
	brr[sum] = 1;
	for(int i =1;i < len;i++)
	{
		if(brr[top] != arr[i])
		{
			brr[sum]--;
		}
		else
		{
			brr[sum]++;
		}
		if(brr[sum] == 0)
		{
			brr[top] = arr[i];
			brr[sum] = 1;
		}
	}
	return brr[top];
}
int main()
{
	int arr[] = {1,2,3,2,2,2,5,4,2};
	int len = sizeof(arr)/sizeof(arr[0]);

	int key = Job3(arr,len);//方法二
	printf("%d\n",key);

	return 0;
}

27.左数第 bit 位 置 1

void Job(int num,int bit)
{
	int n=  pow((double)2,(32-bit));    //  num | 2^(32-k)
	num = num | n;
	printf("%d\n",num);
}
int main()
{
	Job(5,31);

	return 0;
}

28.左数第 bit 位置 0

void Job1(int num,int bit)
{
	int n=  pow((double)2,(32-bit));//   num ^ 2(32-k)
	num = num ^ n;
	printf("%d\n",num);
}
int main()
{
	Job1(5,30);

	return 0;
}

29.获取第 bit 位的值

void Job2(int num,int bit)
{
	num = num >>bit-1;//左移 (32 - bit) | 1
	printf("%d\n",(num ^ 1 ? 0:1));
}
int main()
{
	Job2(5,3);

	return 0;
}


30.写一个函数,它从一个字符串中提取一个子字符串,返回值是存储在dst数组中的子字符串的长度

int SubStr(char *dst,char *src,int start,int len)
{
	int count = 0;
	int j ;
	int i ;
	assert(*src != NULL);
	for( i= start,j = 0; i < len ;i++,j++)
	{
		dst[j] = src[i];
		count++;
	}
	dst[j] = '\0';
	return count;
}
int main()
{
	char arr[] = "abcdef";
	char brr[20] ;
	int len = sizeof(arr)/sizeof(arr[0]);
	int start = 2;
	int len1 = SubStr(brr,arr,start-1,len);
	printf("%d %s\n",len1,brr);

	return 0;
}

 31.从一个字符串中除去多于的空格

void Deblank(char *string)
{
	assert(*string != NULL);
	char *pb = string;
	char *pe = string;
	while(*pe != '\0')
	{
		if(*pe == ' ' && *pe++ == ' ')//遇到空格判断后面是否还有空格,有pb走一步,准备覆盖     (pe++)可以修改成pe+1
		{
			pb++;
		}
		while(!isalpha(*pe))//过滤多于空格
		{
			pe++;
		}
		*pb = *pe;//覆盖
		pe++;
		pb++;
	}
	*pb = '\0';
}
int main()
{
	char arr[] = "abc         bcd                 def      dg";
	Deblank(arr);
	printf("%s\n",arr);

	return 0;
}

另一种方法:考虑前后都有空格

void Deblank(char *string)
{
	assert(*string != NULL);
	char *pb = string;
	char *pe = string;
	while(!(isalpha(*pe)))
	{
		pe++;
		pb++;
	}
	while(*pe != '\0')
	{
		if(*pe == ' ' && *(pe+1) == ' ')//遇到空格判断后面是否还有空格,有pb走一步,准备覆盖
		{
			pb++;
		}
		while(!isalpha(*pe) )//过滤多于空格
		{
			if(*pe == '\0')//末尾有空格
			{
				*(pb-1) = '\0';
				return ;
			}
			pe++;
		}
		*pb = *pe;//覆盖
		pe++;
		pb++;
	}
	*pb = '\0';
}

int main()
{
	char arr[] = "       abc         bcd                 def      dg         ";
	Deblank(arr);
	printf("%s\n",arr);

	return 0;
}

32.长度受限的字符串拷贝 

char *My_strcnpy(char *des,const char *src,int n )
{
	assert(des!=NULL&&src!=NULL);
	assert(n>0&&n

33.长度受限的字符串连接函数

char *My_strncat(char *des,const char *src,int n )
{
	assert(des!=NULL&&src!=NULL);
	assert(n>0&&n

34.长度受限的字符串比较

int My_strcnmpy(const char *str1,const char *str2,int n)
{
	assert(str1 != NULL && str2 != NULL);
	assert(n>0&&n *p2)
			{
				return 1;
			}
			else
			{
				return -1;
			}
		}
	}
}

35.查找字符ch,在给定字符串出现的最后一次

int My_strrchr(const char *str,char ch)
{
	assert(str != NULL);
	for(int i = strlen(str)-1;i >= 0;i--)
	{
		if(str[i] == ch)
		{
			return i;
		}
	}
}

36.字符串查找给定字符,第n次出现的位置

int My_strnchr(const char *str,char ch,int n)
{
	assert(str != NULL);
	int count = 0;
	for(int i = 0;i < strlen(str);i++)
	{
		if(str[i] == ch)
		{
			count++;
			if(count == n)
			{
				return i;
			}
		}
	}
}

37.strlen()函数实现

int My_strlen(const char *str)
{
	assert(str != NULL);
	int len = 0;
	while(*str != '\0')
	{
		len++;
		str++;
	}
	return len;
}

38.strchr()函数实现

int My_strchr(const char* str,char ch)
{
	assert(str != NULL);
	int count = 0;
	while(*str != '\0')
	{
		if(*str == ch)
		{
			return count;
		}
		count++;
		str++;
	}
}

39.strstr()函数实现

int My_strstr(char *str1, char *str2)
{
	assert(str1 != NULL && str2 != NULL);
	char *pb = str1;
	char *pe = str2;
	int i = 0;
	int j = 0;
	while(i < strlen(str1) && j < strlen(str2))
	{
		if(pb[i] == pe[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i-j+1;
			j = 0;
		}
	}
	if(j == strlen(str2))
	{
		return i-strlen(str2);
	}
}
int main()
{
	char arr[] = "abcdefghijklmnopqrst";
	char brr[] = "hij";
	printf("%d\n",My_strlen(arr));
	char d = 'd';
	printf("%d\n",My_strstr(arr,brr));

	return 0;
}

40.单位矩阵3阶

void Identity_matrix(int (*p)[3] ,int row,int col)
{
	for(int i =0;i < row;i++)
	{
		for(int j =0;j < col;j++)
		{
			if(i == j)
			{
				p[i][j] = 1;
			}
			else
			{
				p[i][j] = 0;
			}
		}
	}
	for(int i = 0;i < row; i++)
	{
		for(int j = 0;j < col;j++)
		{
			printf("%d ",p[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int p[3][3];
	Identity_matrix(p,3,3);
	
	return 0;
}

单位矩阵1阶

void Identity_matrix(int *p ,int row,int col)
{
	assert(p != NULL);
	p[0] = 1;
	printf("%d\n",p[0]);
}
int main()
{
	int q[1][1];
	Identity_matrix(p,1,1);

	return 0;
}

41.将字符串中的空格替换为#25

int Job(char *arr)
{
	assert(arr != NULL);
	int count = 0;
	while(*arr != '\0')
	{
		if(*arr == ' ')
		{
			count++;
		}
		arr++;
	}
	return count;
}
char* Job1(char *arr,int len,char *brr)
{
	assert(arr != NULL);
	while(*arr != '\0')
	{
		if(*arr == ' ')
		{
			*brr = '#';
			brr++;
			*brr = '2';
			brr++;
			*brr = '5';
			brr++;
			arr++;
		}
		else
		{
			*brr = *arr;
			brr++;
			arr++;
		}
	}
	*brr = '\0';
	return brr;
}
int main()
{
	char arr[] = "i am tulun";
	int len = sizeof(arr)/sizeof(arr[0]);
	char *brr = (char *)malloc(sizeof(char)*(len + Job(arr)*3));
	Job1(arr,len,brr);
	printf("%s\n",brr);

	return 0;
}

42.将字符串中的字符'*'移到字符串的前面 如:"tu**lu**n**ba**by",处理后为:"********tulunbaby 

char* Job2(char * arr,char *brr,int len)
{
	assert(arr != NULL);
	int j = 0;
	for(int i = 0;i < len;i++)
	{
		if(arr[i] == '*')
		{
			brr[j] = arr[i];
			j++;
		}
		else
		{
			continue;
		}
	}
	for(int i = 0;i < len ;i++)
	{
		if(isalpha(arr[i]))
		{
			brr[j] = arr[i];
			j++;
		}
	}
	brr[j] = '\0';
	return brr;
}
int main()
{
	char arr[] = "tu**lu**n**ba**by";
	int len = sizeof(arr)/sizeof(arr[0]);
	char *brr = (char *)malloc(sizeof(char)*len);
	Job2(arr,brr,len);
	printf("%s\n",brr);

	return 0;
}


/*
(1) va_list:   定义一个va_list型的变量ap,也就是char *;
(2) va_start:获取到可变参数表的首地址,并将该地址赋给指针ap;
(3) va_arg:  获取当前ap所指向的可变参数,并将指针ap指向下一个可变参数。注意,该宏的第二个参数为类型;
(4) va_end: 结束可变参数的获取。
*/

43.可变参数编程,求和.int sum(int count,..)

int Sum(int count,...)
{
	char *p =NULL;
	p = (char *)(&(count))+sizeof(count);
	int sum = 0;
	for(int i = 0;i < count;i++)
	{
		sum += *(int *)((p += sizeof(int))-sizeof(int));
	}
	p = NULL;
	return sum;
}
int main()
{
	printf("%d\n",Sum(2,10,20));

	return 0;
}

44.可变参数编程,多种输出.void Print(const char *str,...)

同一类型

void Print(int count,...)//10,20
{
	char *p =NULL;
	p = (char *)(&(count))+sizeof(count);
	int tmp = 0;
	for(int i = 0;i < count;i++)
	{
		tmp = *(int *)((p += sizeof(int))-sizeof(int));
		printf("%d\n",tmp);
	}
	p = NULL;
}

不同类型

void Print(const char *str,...)
{
	char* list = NULL;
	list = (char*)(&str) + sizeof(str);
	int num;
	int ch;
	char *p;
	double d;
	while(*str != '\0')
	{
		if(*str == '%')
		{
			switch(*(str+1))
			{
			case 'd':
				num = ( *(int *)((list += sizeof(int)) - sizeof(int)) );
				printf("%d",num);
				str += 2;
				break;
			case 'c':
				ch = ( *(char *)((list += sizeof(char)) - sizeof(char)) );
				putchar(ch);
				str += 2;
				(char *)list += 3;
				break;
			case 's':
				p = ( *(char **)((list += sizeof(char*)) - sizeof(char*)) );
				printf("%s",p);
				str += 2;
				break;
			case 'f':
				d =( *(double *)((list += sizeof(double)) - sizeof(double)));
				printf("%f",d);
				str += 2;
				break;
			default:
				putchar(*str++);
				break;
			}
		}
		else
		{
			putchar(*str++);
		}
	}
	list = NULL;
}
int main()
{
	Print("%%,%s,%d,%c,%f\n","hello",10,'a',12.5);

	return 0;
}

45.非常规方法比较两个数的大小

int  Max(int a,int b)
{
	return (a - b) >>31 ? -1: (a-b ? 1 : 0);
}
int main()
{
	printf("%d\n",Max(20,30));
	return 0;
}

46.写一个函数返回bool值,来判断给定的字符串A和B(假设都是小写字母),是否是B中的字符都存在于A中,如果是返回true,否则返回false

bool CheckString(const char *A,const char *B)
{
	bool crr[127] = {false};//bool crr[127] = {true};只有第一个是true,后面的是false。如果初始化为false,后面的都是false
	while(*A != '\0')
	{
		crr[*A] = true;
		A++;
	}
	while(*B != '\0')
	{
		if(!crr[*B])
		{
			return false;
		}
		B++;
	}
	return true;

}

int main()
{
	char arr[] = "abcde";
	char brr[] = "bcd";
	printf("%d\n",CheckString(arr,brr));
	return 0;

}

47.LeetCode06:将一个给定的字符串根据给定的行数以从上往下,从左到右进行Z字形排列。

  方法一 + 方法二

/*
方法一:动态开辟二维数组
*/
void Job(char *arr,int row)//                row行    col列
{
	assert(arr != NULL);
	if(row == 1)
	{
		printf("%s\n",arr);
		return ;
	}
	int col = strlen(arr)/(2*row-2)*(row-1);//求得列数
	int len = strlen(arr) ;
	char **brr;
	brr = (char **)calloc(row,sizeof(char *));//先行后列    先有楼层,才有楼牌号
	for(int i = 0;i < row;i++)
	{
		brr[i] = (char *)calloc(col,sizeof(char));
	}
	int i = 0;
	int j =0;
	int r =0;//记录列数
	int k =0;//记录arr的长度
	while(k < len)
	{
		i = 0;
		r = 0;
		while(r  0;z--,i--,k++,j++)//放不完整一列     放(row-2)次
		{
			if(k < len)
			{
				brr[i][j] = arr[k];
			}
		}
	}
	for(i = 0;i < row;i++)
	{
		for(j = 0;j < col;j++)
		{
			printf("%c",brr[i][j]);
		}
		printf("\n");
	}
	for(i = 0;i < row;i++)//释放,先释放一维
	{
		brr[i];
	}
	free(brr);//再释放二维
}
//方法二:根据数学关系进行变换
char* Convert(char* s, int numRows) 
{
	assert(s != NULL);
	if(numRows == 1)
	{
		return s;
	}
    int len = strlen(s)+1;
	char *arr = (char*)malloc(sizeof(char)*len);
	int cycLen = 2 * numRows-2;
	int k = 0;
	for(int i = 0;i < numRows; i++)
	{
		for(int j = i; j < len-1;j += cycLen)
		{
			arr[k++] = s[j];	
			if (i != 0 && i != numRows - 1 && j + cycLen - 2*i < len-1)
			{
				arr[k++]= s[j + cycLen - 2*i];
			}
		}
	}
	arr[k] = '\0';
	return arr;
}

int main()
{
        char arr[] = "LEETCODEISHIRING";//方法一
	//测试一
	int row = 3;
	Job(arr,row);
	//测试二
	int row1 = 4;
	Job(arr,row1);
	//测试三
	int row2 = 1;
	Job(arr,row2);

	char s[] ="LEETCODEISHIRING";//方法二
	//测试一
	char *brr = NULL;
	int numRows = 3;
	brr = Convert(s,numRows);
	printf("%s\n",brr);
	free(brr);
	//测试二
	char *brr1 = NULL;
	int numRows1 = 4;
	brr = Convert(s,numRows1);
	printf("%s\n",brr);
	free(brr1);
	//测试三
	char *brr2 = NULL;
	int numRows2 = 1;
	brr = Convert(s,numRows2);
	printf("%s\n",brr);
	free(brr2);
        return 0;
}

 48.LeetCode30:与所有单词相关联的字串

给定一个字符串S和一些长度相同的单词words,在S中恰好可以找出串联words中所有单词的子串的起始位置。
子串要与words中的单词完全匹配,中间不能有其他字符,但不需要考虑words中单词串联的顺序。

如:S ="barfoothefoobarman",
words = {"foo","bar"}
输出:[0,9]
解释从索引0和9开始的子串分别是"barfoo"和"foobar"
输出的顺序不重要,[9,0]也是有效答案

方法一 + 方法二

#include
#include
#include
#include
#define SIZE 4
//方法一:使用两个哈希表进行比对;一个存单词和出现次数;另一个在遍历字符串时记录出现次数是否和第I个//一样;一样则找到;不一样则继续遍历
int* FindSubstring(char* s, char  (*words)[4],int many, int len, int* brr)
{
	assert(s != NULL && words != NULL && brr != NULL);
	unsigned char arr[255] = {0}; 
	int len1 = strlen(s);
	int k = 0;
	for(int i = 0;i < many;i++)
	{
		for(int j = 0;j < len;j++)
		{
			arr[words[i][j]]++;
		}
	}
	for(int i = 0;i < len1-many*len;i++)
	{
		unsigned char tmp[255] = {0};
		int j ;
		for(j = i; j < i+many*len;j++)
		{
			if(arr[s[j]])
			{
				tmp[s[j]]++;
				if(arr[s[j]] < tmp[s[j]])
				{
					break;
				}
			}
			else
			{
				break;
			}
		}
		j = j-i;
		if(j == many*len)
		{
			brr[k] = i;
			k++;
			//i = i+many*len;
		}
	}
	return brr;
}

//方法二:计算每个单词出现的位置,每个单词出现的位置+字长是否等于下一个单词出现的位置
int* FindSubstring(char* s, char (*words)[SIZE], int many,int size, int* returnSize) 
{
	assert(s != NULL && words != NULL );
	int len = strlen(s);
	int k = 0;
	int l = 0;
	int tmmp[20] = {0};
	for(int i = 0; i < many; i++)
	{
		char tmp[SIZE];
		for(int j = 0 ; j < len ; j++)
		{
			tmp[0] = s[j++];
			tmp[1] = s[j++];
			tmp[2] = s[j++];
			tmp[3] = '\0';
			if(!strcmp(tmp,words[i]))
			{
				tmmp[k++] = j-3;
				j +=2;
			}
			j -= 3;
		}
	}
	int *arr = (int *)malloc(sizeof(int)*k);
	for (int i = 0; i < k;i++)
	{
		for(int j = 0 ; j < k ;j++)
		{
			if(i == j)
			{
				continue;
			}
			if((tmmp[i] +size) == tmmp[j] )
			{
				arr[l++] = tmmp[i];
			}
		}
	}
	*returnSize = l;
	return arr;
}
int main()
{
	//测试一
	char arr[][4]={"foo","bar"};//方法一
	char s[] = "barfoothefoobarman";
	int *drr = (int *)calloc(2,sizeof(int));
	drr = FindSubstring(s,arr,2,3,drr);
	for(int i =0;i<2;i++)
	{
		if(drr[i] == 0 && i != 0)
		{
			continue;
		}
		printf("%d\n",drr[i]);
	}
	//测试二
	char arr1[][4]={"ood","stu"};
	char s1[] = "goodgoodstudydaydayup";
	int *drr1 = (int *)calloc(2,sizeof(int));
	drr1 = FindSubstring(s1,arr1,2,3,drr1);
	for(int i =0;i<2;i++)
	{
		if(drr1[i] == 0 && i != 0)
		{
			continue;
		}
		printf("%d\n",drr1[i]);
	}
	//测试三
	char arr2[][4]={"foo","bar"};
	char s2[] = "bofarothefoobarman";
	int *drr2 = (int *)calloc(2,sizeof(int));
	drr2 = FindSubstring(s2,arr2,2,3,drr2);
	for(int i =0;i<2;i++)
	{
		if(drr2[i] == 0 && i != 0)
		{
			continue;
		}
		printf("%d\n",drr2[i]);
	}

	//char s[] = "barfoothefoobarman";//方法二
	//char words[][SIZE] = {"foo","bar"};
	//int *arr = NULL;
	//int returnSize ;
	//arr = FindSubstring(s,words,2,3,&returnSize);
	//for(int i = 0; i < returnSize; i++)
	//{
	//	printf("%d\n",arr[i]);
	//}
	//free(arr);

	return 0;
}

 

你可能感兴趣的:(C,C)