C语言刷题练习

【程序1】

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

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4, };
	int i = 0;
	int j = 0;
	int k = 0;
	int count = 0;
	for (i = 1; i < 5; i++)
	{
		for (j = 1; j < 5; j++)
		{
			for (k = 1; k < 5; k++)
			{
				if (i != j && i != k && j != k)//这个地方非常明智
					//不用过多考虑如何实现这三位数的数字不能重复
					//可以理解为,你想干什么就直接把事情扔给代码干
					//不要担心写出bug,把事情交给代码做就行了
					//这个思维和做递归题有点相似,即不用考虑太深!!
				{
					printf("%d\n", i * 100 + j * 10 + k);
					//这个地方也挺巧妙的,本来想用一个数字一个数字打印的方法
					//但是方法太挫
					count++;
				}

			}
		}
	}
	printf("一共有%d种组合\n", count);
	return 0;
}

【程序2】

题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

#include<stdio.h>

int main()
{
	int i = 0;
	for (i = 1; i < 10000; i++)
	{
		double b = sqrt(i+100);
		double c = sqrt(i + 168);
		double d = (int)b;
		double e = (int)c; //强制类型转换成整数来舍去小数,我太聪明了呜呜呜
		if (d == b && e == c)
		{
			printf("%d", i);
			break;
		}
	}
	return 0;
}

【程序3】

题目:打印9*9乘法表

#include<stdio.h>
#define ROW 9
#define COL 9
int main()
{
	int i, j;
	for (i = 1; i < ROW + 1; i++)
	{
		for (j = 1; j <= i; j++) //这个j<=i是关键,能保证不重复打印
		{
		    printf("%d*%d=%2d ", j, i, i * j);
		}
		printf("\n");
	}
	return 0;
}

【程序4】

题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?

#include<stdio.h>
//递归法,但容易栈溢出
int Fibonacci(int m)
{
	if (m <= 2)
	{
		return 1;//这里本来写错写成了return m,会影响后续返回的值导致错误
	}
	else
	{
		return Fibonacci(m - 1) + Fibonacci(m - 2);
	}
}
int main()
{
	int month;
	scanf("%d", &month);
	int ret = Fibonacci(month);
	printf("%d", ret);
	return 0;
}
#include<stdio.h>
//循环法,不会栈溢出
int Fibonacci(int m)
{
	int a = 1;
	int b = 2;
	int c = 0;
	while (m > 2)
	{
		c = a + b;
		a = b;
		b = c;
		m--;
		/*return c;*///在这里写错了,不能把return放在循环里,不然无法开始下一次循环就返回值了

	}
	return c;
}
int main()
{
	int month;
	scanf("%d", &month);
	int ret = Fibonacci(month);
	printf("%d", ret);
	return 0;
}

【程序5】

实现my_strcpy

​
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
    assert(dest != NULL);//断言,若地址不为空则真
	assert(src != NULL);
	while (*dest++ = *src++)
	{
		;
	}
	return ret;//返回dest的首元素地址
}
int main()
{
	char arr1[20] = "xxxxxxxxxxxxxxxx";
	char arr2[20] = "hello bit";
	printf("%s", my_strcpy(arr1, arr2));//链式访问
	return 0;
}

​

【程序6】

实现my_strlen

#include<stdio.h>
#include<assert.h>
//size_t == unsigned int,无符号整形(正整数)
size_t my_strlen(char* str)
{
	size_t count = 0;
	assert(str);
	while (*str++ != '\0')
	{
		count++;
	}
	return count;
}
int main()
{
	char arr[20] = "ajhfunsdfoig";
	printf("%d", my_strlen(arr));
	return 0;
}

【程序7】

题目:将一个正整数分解质因数。例如:输入90,打印出90=2 * 3 * 3 * 5。

#include<stdio.h>
int main()
{
	int a;
	int i;
	scanf("%d", &a);
	if (a == 1)
	{
		printf("%d = %d", a, a);
	}
	else
	{
		printf("%d = ", a);
	again:
		for (i = 2; i <= a; i++)
		{
			if (a % i == 0)
			{
				a = a / i;
				printf("%d ", i);
				if (a != 1)
				{
					printf("* ");
				}
				goto again;
			}


		}
	}
	return 0;
}

【程序8】

题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。

#include<stdio.h>
//题目:利用条件运算符的嵌套来完成此题:学习成绩 >= 90分的同学用A表示,60 - 89分之间的用B表示,60分以下的用C表示。
int main()
{
	char level = '0';//因最终成绩要表示为A,B,C,要想到打印的是字符
	                 //故建立一个char类型来接受最后返回的成绩等级
	unsigned int goal;
	scanf("%d", &goal);
	level = goal >= 90 ? 'A' : (goal > 60 && goal < 89 ? 'B' : 'C');
	printf("%c", level);
	return 0;
}

【程序9】

题目:输入两个正整数m和n,求其最大公约数和最小公倍数。

#include<stdio.h>
int main()
{
	int m, n;
	
	int i;
	scanf("%d%d", &m, &n);
	int l = n;
	int k = m;
	if (m > n)
	{
		for (i = n; i >= 0; i--)
		{
			if (m % i == 0 && n % i == 0)
			{
				printf("最大公约数为:%d\n", i);
				break;
			}
		}
	}
	else
	{
		for (i = m; i >= 0; i--)
		{
			if (m % i == 0 && n % i == 0)
			{
				printf("最大公约数为:%d\n", i);
				break;
			}
		}
	}
	printf("最小公倍数为:%d", l * k / i);
	return 0;
}

【程序10】

求一个整数存储在内存中二进制中1的个数

#include<stdio.h>
int main()
{
	int i;
	int n;
	scanf("%d", &n);
	int count = 0;
	for(i = 0; i < 32; i++)//因为二进制中有32位,所以要对比32次
	{
		if (((n >> i) & 1) == 1)
		{
			count++;
		}
		
	}
	printf("%d", count);
	return 0;
}

优化如下

#include<stdio.h>
int main()
{
	int i;
	int n;
	scanf("%d", &n);
	int count = 0;
	while (n)
	{
		n = n & (n - 1);//思路是每次都去掉最右的1,计数运行了几次&
		//如果n=15
		//1111  n
		//1110  n-1
		//&后
		//1110  n
		//1011  n-1
		//&后
		//1010  n
		//1001  n-1
		//&后
		//1000  n
		//0111  n-1
		//&后
		//0000 n
		count++;
	}
	printf("%d", count);
	return 0;
}

【程序10】

求两个数的二进制数中,有多少位不相同

#include<stdio.h>
int main()
{
	int m;
	int n;
	scanf("%d%d",&m, &n);
	int ret = m ^ n;
	int count = 0;
	while (ret)
	{
		ret = ret & (ret - 1);

		count++;
	}
	printf("%d", count);
	return 0;
}

【程序11】

打印n的二进制中的奇数位和偶数位

#include<stdio.h>
int main()
{
	int n;
	int i;
	scanf("%d", &n);
	for (i = 31; i > 0; i -= 2)//奇数位
	{
		printf("%d ", (n >> i) & 1);
	}
	printf("\n");
	for (i = 30; i >= 0; i -=2)//偶数位
	{
		printf("%d ", (n >> i) & 1);

	}
	return 0;
}

【程序12】

交换两个变量的值,不能创建临时变量

#include<stdio.h>
int main()
{
	int a = 2;
	int b = 6;
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a=%d b=%d", a, b);
	return 0;
}

【程序13】

 for循环第一次不会执行x++

 14.

11:0000......1011

12:  0000......1010

11||12:0000......1011

【程序14】

将一句话的单词进行倒置,标点不倒置,例如 I like Beijing. 倒置后变为 Beijing. like I

#include<stdio.h>
void reverse(char* left, char* right)
{
	while (left < right)
	{
		char temp = *left;
		*left = *right;
		*right = temp;
		left++;
		right--;
	}
}
int main()
{
	char arr[100] = { 0 };
	gets_s(arr);
	//倒置全部
	int sz = strlen(arr);
	reverse(arr, arr + sz - 1);
	char* start = arr;

	while (*start)
	{
		char* end = start;
		while (*end != ' ' && *end != '\0')
		{
			end++;
		}
		reverse(start, end - 1);
		if (*end == ' ')
		{
			
			start = end + 1;
		}
		else
		{
			break;
		}


	}
	printf("%s", arr);
	return 0;
}

【程序15】

题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。

#include<stdio.h>
int main()
{
	int num;
	int i = 0;
	int characetercount = 0;//字母
	int blankcount = 0;//空格
	int numcount = 0;//数字
	int othcount = 0;//其他
	char arr[100] = { 0 };
	gets_s(arr);
	while (arr[i])
	{
		num = arr[i] + 0;//字符类型转数字类型
		if (num >= 65 && num <= 90 || (num >= 97 && num <= 122))
		{
			characetercount++;
		}
		else if (num == 32)
		{
			blankcount++;
		}
		else if (num >= 48 && num <= 57)
		{
			numcount++;
		}
		else
		{
			othcount++;
		}
		i++;
	}
	printf("字母:%d\n", characetercount);
	printf("空格:%d\n", blankcount);
	printf("数字:%d\n", numcount);
	printf("其他:%d\n", othcount);
	return 0;
}

【程序16】

题目:求s=a+aa+aaa+aaaa+aa…a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加有键盘控制。

分析:递归求第n项数字好用,求前n项和不太好用,还是循环比较方便。这一题能用递归,情况还是比较特殊好考虑到的

#include<stdio.h>
int main()
{
	int a = 0;
	int n = 0;
	int temp = 0;
	int sum = 0;
	int i = 0;
	scanf("%d%d", &a, &n);
	for (i = 0; i < n; i++)
	{
		temp = a + temp * 10;
		sum += temp;
	}
	printf("%d",sum );
	return 0;
}

#include<stdio.h>
int ret(int a, int n)
{
	int temp = 0;
	
	if (n-1)
	{
		return a * n  + ret(a, n - 1) * 10;
	}
	else
	{
		return a;
	}
}
int main()
{
	int a = 0;
	int n = 0;
	int temp = 0;
	int sum = 0;
	int i = 0;
	scanf("%d%d", &a, &n);
	/*for (i = 0; i < n; i++)
	{
		temp = a + temp * 10;
		sum += temp;
	}*/
	sum = ret(a, n);
	printf("%d",sum );
	return 0;
}

【程序17】

题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?

这题用递归方便是因为,前n项和 = 前一项和 + 高度

#include<stdio.h>
double NUM(double high, int num)
{
	for (num; num > 1; num--)
	{
		high /= 2;
	}
	return high;
}
double SUM(double high,int num)
{
	if (num <= 1)
	{
		return 100;
	}
	else
	{
		return SUM(high/2, num - 1) + high;
	}
}
int main()
{
	double high = 100;
	int num = 0;
	scanf("%d", &num);
	double sum = 0;
	sum = SUM(high,num);
	printf("第n次反弹经过的路程:%lf\n", sum);
	printf("第n次反弹的高度:%lf", NUM(high, num));
	return 0;
}

【程序18】

题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个.第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。

第10天,1
第9天,4
第8天,10
第7天,22

#include<stdio.h>
int main()
{
	int i = 0;
	int peach = 0;

	peach = 1;
	for (i = 1; i < 10; i++)
	{
		peach = (peach * 2 + 2);
		printf(" 第%d天的桃子数为:%d\n ", 10 - i, peach);
	}
	return 0;
	
}

【程序19】

题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前20项之和。

分析:创建临时变量存储分子和分母

#include<stdio.h>
double SUM(n)
{
	double a = 2;
	double b = 1;
	double c = 0;
	double sum = 0;
	while (n--)
	{
		c = a / b;
		sum = sum + c;
		int temp = b;
		b = a;
		a = a + temp;
	}
	return sum;

}
int main()
{
	int n;
	printf("求前n项和:");
	scanf("%d", &n);
	double sum = SUM(n);
	printf("该数列前n项和:%lf", sum);
	return 0;
	
}

【程序20】

题目:求1+2!+3!+…+20!的和

例如这题,就用不了递归,顶多用递归算出n!,要相加所有项还是得用循环 c

#include<stdio.h>
int main()
{

	int n = 0;
	int sum = 0;
	int i = 1;
	int j;
	scanf("%d", &n);
	if (n == 1)
	{
		printf("和:1");
	}
	else
	{
		for (j = 1; j <= n; j++)
		{
			int temp = 1;

			for (i = 1; i <= j; i++)
			{
				
				temp = temp * i;
				
			}
			sum = sum + temp;

		}
		printf("和:%d", sum);
	}
	
	return 0;
	
}

【程序21】

#include<stdio.h>
#include<string.h>
//大端字节序:把低位字节序存放在高地址,把高位字节序存放在低地址。
//小端字节序:把低位字节序存放在低地址,把高位字节序存放在高地址。
void check_sys()
{
    int a = 1;
    //00 00 00 01
    char* pa = (char*) & a;//用char*指针是因为其每次只访问一个字节,例如访问00->00->00->01
    if (*pa == 1)
    {
        printf("大端");
    }
    else
    {
        printf("小端");
    }
}
int main()
{
    check_sys();
    return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
union U
{
	int i;
	char a;
}un;
int main()
{
	un.i = 1;
	if (un.a == 0)
	{
		printf("小端");
	}
	else
	{
		printf("大端");
	}
	return 0;
}

【程序22】

-1是负数,都以补码形式储存,整数存到char里,又因为char类型只存放八个bit位,于是截断前八个bit位,再存放到a,b和c里。又因为printf有%d,所以a和b被整形提升,高位补充符号位。

而c是无符号整型提升,高位补0。

*值得补充的是,未达到int类型大小的(char和short)在运算时都会进行整形提升

例如:char a, b, c

            a = b + c

b和c都被提升为整形,再加法运算,运算完成后,结果被截断,再存于a中。

【程序22】

冒泡排序

#include<stdio.h>
void Bubbsort(int arr[5], int len)
{
	int i = 0;
	int j = 0;
	int temp = 0;
	for (i = 0; i < len - 1; i++)
	{
		for (j = 0; j < len - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
int main()
{
	int input[20] = { 1,2,6,4,3,9,90,32,99,78 };
	int len = 10;
	int i = 0;
	Bubbsort(input,len);
	for (i = 0; i < len; i++)
	{
		printf("%d ", input[i]);
	}
	return 0;
	
}

【程序23】

题目:有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。

分析:要创建两个数组

#include<stdio.h>
int main()
{
	int a[20] = { 1,3,5,7,9,11 };
	int b[20] = { 0 };
	int my;
	scanf("%d", &my);
	int i;
	for (i = 0; i < 6; i++)
	{
		if (my <= a[i] && my != 0)
		{
			b[i] = my;
			break;
		}
		else if (my > a[5])
		{
			b[6] = my;
			goto con2;
		}
		else if (my <= 0)
		{
			b[0] = my;
			goto con1;
		}
		else
		{
			;
		}

	}
	int k,l,m;
	for (k = 0; k < i; k++)
	{
		b[k] = a[k];
	}
	for (l = i + 1; l <= 6; l++)
	{
		b[l] = a[l - 1];
	}
	if (my <= 0)
	{
	con1:
		for (l = 1; l <= 6; l++)
		{
			b[l] = a[l - 1];
		}
	}
	if (my > a[5])
	{
	con2:
		for (l = 0; l < 6; l++)
		{
			b[l] = a[l];
		}

	}

    for (m = 0; m <= 6; m++)
	{
		printf("%d ", b[m]);
	}
	

	return 0;
}

优化:唉,太傻了,上面那个代码想直接考虑输入的数的种种情况,实际上直接把输入的数放进数组里,再用冒泡排序法就行了。

啊啊啊啊啊花了那么多时间写了个劣质代码,以后做题前一定要多想想,没准有更优的解法!

#include<stdio.h>
void Bubble_sort(int arr[5], int len)
{
	int i = 0;
	int j = 0;
	int temp = 0;
	for (i = 0; i < len - 1; i++)
	{
		for (j = 0; j < len - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
int main()
{
	int arr[20] = { 1,3,5,7,9,11 };
	int my;
	int i;
	scanf("%d", &my);
	arr[6] = my;
	int len = 7;
	Bubble_sort(arr,len);
	for (i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

【程序24】

题目:输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。

#include<stdio.h>
void Bubble_sort(int arr1[20], int len)
{
	int i = 0;
	int j = 0;
	int temp = 0;
	for (i = 0; i < len - 1; i++)
	{
		for (j = 0; j < len - 1 - i; j++)
		{
			if (arr1[j] > arr1[j + 1])
			{
				temp = arr1[j];
				arr1[j] = arr1[j + 1];
				arr1[j + 1] = temp;
			}
		}
	}
}
int main()
{
	int arr1[20] = { 1,5,3,-2,6,5,-1000,-78,0,243 };//将要被冒泡排序的数组
	int arr2[20] = { 1,5,3,-2,6,5,-1000,-78,0,243 };//要被打印的数组
	int len = 10;
	Bubble_sort(arr1,len);
	int temp1 = arr1[0];//最小数
	int temp2 = arr1[len-1];//最大数
	int temp3 = arr2[0];//第一位数
	int temp4 = arr2[len-1];//最后一位数
	arr2[0] = temp2;//第一位变成最大数
	int i, j;
	for (j = 1; j < len; j++)//原有的第一个元素放到原最大元素的位置
	{
		if (arr2[j] == temp2)
		{
			arr2[j] = temp3;
			break;
		}

	}
	int temp5 = arr2[len-1];//因为在上面的步骤中,最后一位可能会被替换,所以要重新建立临时变量储存最新的最后一个数
	arr2[len-1] = temp1;//最后一位数变成最小数
	for (j = 1; j < len; j++)//原有的最后一个元素放到原最小元素的位置
	{
		if (arr2[j] == temp1)
		{
			arr2[j] = temp5;
			break;

		}
		
	}

	for (i = 0; i < len; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

优化如下:

【程序25】

学习gotoxy()

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
void gotoxy(int x, int y)      //光标移动到(x,y)位置
{
    HANDLE handle;
    //HANDLE  handle; 这里和COORD 是一样的,HANDLE是一个一定由系统定制的结构体,直接调用就可以。
    //将获得的标准输出句柄给handle。
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
    //GetStdHandle () 这个函数也是C语言内部已经设定好的,所以这里直接调用就行。
    //GetStdHandle(STD_OUTPUT_HANDLE) 这里就是一个固定的函数格式,获得标准输出函数的句柄。


    COORD pos;//COORD实际上是一个C语言内部做好的结构体,
              //结构体中只包含两个元素,x和y,这里的x、y就是代表着光标移动的位置
              //只不过这里不需要你再去定义一个结构体,直接调用就可以。
              //这个结构体就是用来记录坐标。
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
    //移动光标的意思,也是由C语言直接提供给你的,直接使用就可以
}

int main()
{
    gotoxy(5, 5);   
    printf("1");
    gotoxy(5, 6);
    printf("2");
    return 0;
}

【程序26】

题目:求一个3*3矩阵对角线元素之和。

分析:
题目的意思没表达清楚,应该是主对角线元素(左上至右下角元素)之和

#include<string.h>
void InitBoard(int arr[3][3])
{
    int i, j;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            scanf("%d", &arr[i][j]);//注意这个地方要加&
        }
    }
}


void PrintBoard(int arr[3][3])
{
    int i, j;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}
int SUM(int arr[3][3])
{
    int i = 0;
    int j = 0;
    int sum = 0;
    for (i = 0; i < 3; i++)
    {
        sum = sum + arr[i][j];
        j++;
    }
    return sum;
}
int main()
{
    int arr[3][3];
    InitBoard(arr);
    PrintBoard(arr);
    printf("%d", SUM(arr));
    return 0;
}

【程序27】

打印杨辉三角

int Calculate(int arr[100][100], int n,int row, int col)
{
    if (col <= 0 || col >= n - 1)
    {
        return 1;
    }
    else
    {
        return arr[row - 1][col - 1] + arr[row - 1][col];
    }
}
void InitBoard(int arr[100][100],int n)
{
    int ROW = 0;
    int COL = 0;
    for (ROW = 0; ROW < n; ROW++)
    {
        for (COL = 0; COL <= ROW; COL++)
        {
            arr[ROW][COL] = Calculate(arr,n,ROW,COL);
        }
    }
}
void Print(int arr[100][100], int n)
{
    int ROW = 0;
    int COL = 0;
    
    for (ROW = 0; ROW < n; ROW++)
    {
        for (COL = 0; COL <= ROW; COL++)
        {
           
            printf("%d ", arr[ROW][COL]);
        }
        printf("\n");
    }
}
int main()
{
    int n;
    scanf("%d", &n);//打印到杨辉三角的第n行
    int arr[100][100] = { 0 };
    InitBoard(arr,n);
    Print(arr, n);
    return 0;
}

不用递归的写法,其实也类似

void InitBoard(int arr[100][100], int n)
{
    int ROW = 0;
    int COL = 0;
    for (ROW = 0; ROW < n; ROW++)
    {
        for (COL = 0; COL <= ROW; COL++)
        {
            if (COL == 0)
            {
                arr[ROW][COL] = 1;
            }
            if (COL == ROW)
            {
                arr[ROW][COL] = 1;
            }
            
            if (ROW >= 2 && COL >= 1)
            {
                arr[ROW][COL] = arr[ROW - 1][COL - 1] + arr[ROW - 1][COL];
            }
        }
    }
}
void Print(int arr[100][100], int n)
{
    int ROW = 0;
    int COL = 0;

    for (ROW = 0; ROW < n; ROW++)
    {
        for (COL = 0; COL <= ROW; COL++)
        {

            printf("%d ", arr[ROW][COL]);
        }
        printf("\n");
    }
}
int main()
{
    int n;
    scanf("%d", &n);//打印到杨辉三角的第n行
    int arr[100][100] = { 0 };
    InitBoard(arr, n);
    Print(arr, n);
    return 0;
}

【程序28】

题目:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

#include<windows.h>
void Initcycle(int n, int arr[500])
{
    int i;
    for (i = 0; i < n; i++)
    {
        arr[i] = i + 1;
    }
}
void out(int n, int arr[500])
{
    int count = 0;
    int ret = n;
    int i = 0;
    int j = 0;
    while (ret != 1)
    {
        for (i = 0; i < n; i++)
        {
            if (arr[i] == 0)
            {
                ;
            }
            else
            {
                count++;
                if (count == 3)
                {
                    count = 0;
                    arr[i] = 0;
                    ret--;
                }
            }
        }
    }
    
    
}
void Print(int n, int arr[500])
{
    int i;
    for (i = 0; i < n; i++)
    {
        if (arr[i] != 0)
        {
            printf("最后剩下的是:%d号\n", arr[i]);
        }
    }
}
int main()
{
    int arr[500] = { 0 };
    int n;
    scanf("%d", &n);//n个人
    Initcycle(n, arr);
    out(n, arr);
    Print(n,arr);
    return 0;
}

【程序29】

判断是什么类型的三角形

分析:判断是否为三角形时,用a+b>c&&a+c>b&&b+c>a 来判断

#include<stdio.h>
int main()
{
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    if (a + b > c && a + c > b && b + c > a)
    {
        if (a == b && a == c)
        {
            printf("ET");
        }

        else if (a != b && a != c && b != c)
        {
            if (a * a + b * b == c * c || a * a + c * c == b * b || b * b + c * c == a * a)
            {
                printf("RT");
            }
            else
            {
                printf("OT");
            }
        }

        else
        {
            printf("IT");
        }
    }
    else
    {
        printf("Not a triangle");
    }

    return 0;
}

【程序30】

题目:编写input()和output()函数输入,输出5个学生的数据记录。

【程序31】

#include<conio.h>
double Sum(int n)
{
    double sum = 0;
    
    
    while (n > 0)
    {
        sum = sum + 1.0 / n;
        n -= 2;
    }
    return sum;
    
}
void print(double sum,int n)
{
    if (n % 2 == 0)//偶数
    {
        int i = 2;
        while (i <= n)
        {
            if (i == n)
            {
                printf("1/%d = %lf",i,sum);
                break;
            }
            printf("1/%d + ", i);
            i += 2;
        }
    }
    else
    {
        int i = 1;
        while (i <= n)
        {
            if (i == n)
            {
                printf("1/%d = %lf", i, sum);

                break;
            }
            printf("1/%d + ", i);
            i += 2;
        }
    }
}
int main() 
{
    int n;
    scanf("%d", &n);
    double sum = Sum(n);
    print(sum,n);
    return 0;
}

【程序32】

int main() 
{
    int n = 0;//n代表还没喝的饮料个数
    scanf("%d", &n);
    int sum = 0;
    
    int ret = 0;
    while (n != 0)
    {
        sum = sum + n;
        ret = ret + n % 2;//用空瓶子换完饮料还剩下不够换饮料的瓶子(0\1)
        n = n / 2;//用空瓶子换的饮料,可以喝
        
        if (ret == 2)
        {
            n = n + 1;
            ret = 0;
        }
    }
    printf("%d", sum);
    return 0;
}

优化如下

int main() 
{
    int money;
    scanf("%d", &money);
    int sum = money;
    int empty = money;
    while (empty >= 2)
    {
        sum = sum + empty / 2;
        empty = empty / 2 + empty % 2;

    }
    printf("%d", sum);
    return 0;
}

【程序33】

打印菱形

void Spacebar(int line)
{
    int i;
    for (i = line - 1; i >= 0; i--)
    {
        printf(" ");
    }
}
void Print(int j)
{
    while (j > 0)
    {
        printf("*");
        j--;
    }
}
int main() 
{
    int line;
    scanf("%d", &line);
    int line2 = line;
    int j = 1;
    while (line > 0)
    {
        Spacebar(line);
        Print(j);
        Spacebar(line);
        printf("\n");
        j += 2;
        line--;
    }
    line = line2 - 1;
    int i = 2;
    int p = 2 * line - 1;
    
    while (line > 0)
    {
        
        Spacebar(i);
        Print(p);
        Spacebar(i);
        printf("\n");
        p -= 2;
        i++;
        line--;
    }
    
    return 0;
}

【程序34】

可关联看程序21

 分析:a是unsigned int 类型,而&a是unsigned int*类型(这个地方暂时不知道怎么理解,就暂时理解成,地址一般用指针来指向的吧),把a强制类型转换成unsigned char*类型,每次只能访问一个字节,故b得到的是00

【程序35】 

分析:巧妙地运用判断为真返回1,判断为假返回0的特性

int main()
{
    char killer;

    for (killer = 'A'; killer <= 'D'; killer++)
    {
        if ((killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D') == 3)
        {
            printf("%c", killer);
        }
    }
    return 0;
}

【程序36】

#include<stdio.h>
int main()
{
    int a, b, c, d, e;
    for (a = 1; a <= 5; a++)
    {
        for (b = 1; b <= 5; b++)
        {
            for (c = 1; c <= 5; c++)
            {
                for (d = 1; d <= 5; d++)
                {
                    for (e = 1; e <= 5; e++)
                    {
                        if ((b == 2) + (a == 3) == 1
                            && (b == 2) + (e == 4) == 1
                            && (c == 1) + (d == 2) == 1
                            && (c == 5) + (d == 3) == 1
                            && (e == 4) + (a == 1) == 1
                            
                            )
                        {
                            if(a*b*c*d*e==120)
                            printf("a:%d,b:%d,c:%d,d:%d,e:%d\n", a, b, c, d, e);
                        }
                    }
                }
            }
        }
    }
    return 0;
}

【程序37】

 

#include<math.h>
int Find(int arr[3][3], int k)
{
	int row = 0;
	int col = 2;
	while (row < 3 && col >= 0)
	{
		if (arr[row][col] < k)
		{
			row++;
		}
		else if (arr[row][col] == k)
		{
			return 1;
		}
		else
		{
			col--;
		}
	}
	return 0;
}
int main()
{
	int arr2[3] = { 1,2,3 };
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int k = 20;
	int ret = Find(arr, k);
	if (ret == 1)
	{
		printf("找到了");
	}
	else
	{
		printf("没找到");
	}
	return 0;
}

【程序38】

void left_spin(char arr[], int n,int sz)
{
    int i;
    char arr2[10] = { 0 };
    for (i = 0; i < sz; i++)
    {
        arr2[i] = arr[i];
        if (i + n < sz)
        {
            arr[i] = arr[i + n];
        }
    }
    for (i = 0; i < n; i++)
    {
        arr[sz - n + i] = arr2[i];
    }
}
int main()
{
    char arr[10] = "ABCDEF";
    int n;
    scanf("%d", &n);
    int sz = strlen(arr);
    left_spin(arr, n,sz);
    printf("%s", arr);
    return 0;
}

【程序39】

方法一:穷举法

方法二:把被比较的字符串再追加一份,判断另一个字符串是不是其子串

int main()
{
	char arr1[10] = "ABCDEFG";
	char arr2[10] = "CDEFGAB";
	int len1 = strlen(arr1);
	int len2 = strlen(arr2);
	if (len1 != len2)
	{
		printf("不是");
	}
	else
	{
		strncat(arr1, arr1, len1);
		char* p = strstr(arr1, arr2);
		if (p == NULL)
		{
			printf("不是");
		}
		else
		{
			printf("是");
		}
	}
	return 0;
}

【程序40】

求0~7的数字能组成奇数的个数,可重复使用

分析:高中排列组合的知识罢了,先确定末尾是奇数,首位为非0数,就可以得出几位数对应有多少奇数的组合

int my_strcount(char* str1, char* str2, int len)
{
	char* str3 = str2;
	int count = 0;
	int n = 0;
	while (*str1 != '\0')
	{
		if (*str1 != *str2)
		{

			str1++;
			str2 = str3;

		}
		else
		{
			str1++;
			str2++;
			n++;
			if (*str2 == '\0')
			{
				count++;

				str2 = str2 - len;
			}
		}
	}
	return count;
}
int main()
{
	char arr1[30] = "abcdhacbabdhabkababj";
	char arr2[30] = "ab";
	int len = strlen(arr2);
	int count = my_strcount(arr1, arr2, len);
	printf("%d", count);
	return 0;
}

【程序41】
题目:计算字符串中子串出现的次数。

int calculate(int n)
{
	
	if (n == 1)
	{
		return 4;
	}

	else if (n == 2)
	{
		return 28;
	}
	else
	{
		return calculate(n - 1) * 8;
	}
}
int main()
{
	//求0~7的数字能组成奇数的个数,可重复使用
	//考虑一位数,两位数......的情况
	int num = 8;
	int n = 0;
	int ret1 = 0;
	int ret2 = 0;
	int temp;
	for (n = 1; n <= 8; n++)
	{
		ret1 = calculate(n);
		temp = ret1;
		ret2 += temp;
	}
	printf("%d", ret2);
	return 0;
}

【程序42】

题目:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。

int main()
{
	/*题目:两个乒乓球队进行比赛,各出三人。
		甲队为a, b, c三人,乙队为x, y, z三人。已抽签决定比赛名单。
		有人向队员打听比赛的名单。a说他不和x比,c说他不和x, z比,
		请编程序找出三队赛手的名单。*/
	char a, b, c;
	char x, y, z;
	for (a = 'x'; a <= 'z'; a++)
	{
		for (b = 'x'; b <= 'z'; b++)
		{
			for (c = 'x'; c <= 'z'; c++)
			{
				if ((a != 'x') + (c != 'x') + (c != 'z') + (a != b) + (a != c) + (b != c) == 6)
				{
					printf("a->%c,b->%c,c->%c\n", a, b, c);
				}
			}
		}
	}
	return 0;
}

【程序43】

鸡兔同笼

分析:先把鸡和兔的数量算出来,进行以下判断

1.鸡是否为正数

2.兔是否为正数

3.脚是否为奇数

把不满足条件的一定要写在  if  里,用来打印无解的情况,

因为放在else里会出错,不知道为什么

int main()
{
	int h, f, ji, tu;
	scanf("%d%d", &h, &f);
	ji = (4 * h - f) / 2;
	tu = h - ji;
	if (f % 2 == 1 || ji < 0 || tu < 0)
	{
		printf("No solution!");
	}
	else
	{
		printf("chickens = %d; rabbits = %d", ji, tu);
	}
	return 0;
}

【程序44】

解二元一次方程

分析:这题要注意三个点

1.要单独考虑 a==0 的情况,否则执行下面其他代码时a==0作为分母,会出错

2.因为当b==0时,打印出的实部会是 -0.00,故加上个负号就能避免

3.因为d < 0,所以要sqrt(-d),否则根号里放负数会出错

#include<stdio.h>
#include<math.h>
#include<windows.h>
int main()
{
	
	float a, b, c;
	scanf("%f%f%f", &a, &b, &c);
	float d = b * b - 4 * a * c;
	if (a == 0 && b == 0 && c != 0)
	{
		printf("Not An Equation");
		return 0;
	}
	if (a == 0 && b == 0 && c == 0)
	{
		printf("Zero Equation");
		return 0;
	}
	if (a == 0 && b != 0 & c != 0)
		//要单独考虑 a==0 的情况,否则执行下面其他代码时a==0作为分母,会出错
	{
		printf("%.2f", -c / b);
		return 0;
	}
		
	if (d == 0)
	{
		double ret1 = (-b + sqrt(d)) / 2 / a;
		double ret2 = (-b - sqrt(d)) / 2 / a;
		printf("%.2f", ret1);
		return 0;
	}
		
	if (d > 0)
	{
		double ret1 = (-b + sqrt(d)) / 2 / a;
		double ret2 = (-b - sqrt(d)) / 2 / a;
		printf("%.2f\n%.2f", ret1, ret2);
		return 0;
	}

	if(d < 0)
	{
		if (b == 0)
		{
			b = -b;
		}
		//因为当b==0时,打印出的实部会是 -0.00,故加上个负号就能避免
		printf("%.2f+%.2fi\n%.2f-%.2fi", -b / 2 / a, sqrt(-d) / 2 / a, -b / 2 / a, sqrt(-d) / 2 / a);
		//因为d < 0,所以要sqrt(-b),否则根号里放负数会出错
		return 0;
	}
	
	return 0;
}

【程序45】

分析:

1.第一步一定是判断是否为三角形

2.要注意锐角三角形的判断条件,任意两条边的平方和都要大于第三边,要用&&

3.而钝角三角形的判断条件,是其中两条边的平方和小于第三边,故用||

int main()
{

	int a, b, c;
	scanf("%d%d%d", &a, &b, &c);
	if (a + b > c && a + c > b && b + c > a)
	{
		
		if (a * a + b * b > c * c && a * a + c * c > b * b && b * b + c * c > a * a)
		{
			printf("Acute Triangle");
			return 0;
		}
        if (a * a + b * b == c * c || a * a + c * c == b * b || b * b + c * c == a * a)
		{
			printf("Right Triangle");
			return 0;
		}
		
		if (a * a + b * b < c * c || a * a + c * c < b * b || b * b + c * c < a * a)
		{

			printf("Obtuse Triangle");
			return 0;
		}
	}
	else
	{
		printf("Not Triangle");

	}
	return 0;
}

【程序46】

int main()
{
	int p, e, i,d;//23,28,33
	scanf("%d%d%d%d", &p, &e, &i,&d);
	int j,k,l;
	if (p == 0 && e == 0 && i == 0)
	{
		k = 21252;
		goto end;
	}
	for (j = p; j <= 21252; j += 23)
	{

		for (k = e; k <= 21252; k += 28)
		{

			for (l = i; l <= 21252; l += 33)
			{

				if (j == k && k == l)
				{
					goto end;
				}
			}
		}
	}
		
	
end:
	printf("%d", k - d);
	return 0;
}

 以下是优化

#include<cstdio>
#include<iostream>
#define N 21252
using namespace std;
int main()
{
	int p,e,i,d;
	int caseNo=0;
	while(cin>>p>>e>>i>>d&&p!=-1){
		caseNo++;
		int k;	
		for(k=d+1;(k-p)%23;k++);
		for(;(k-e)%28;k+=23); 
		for(;(k-i)%33;k+=23*28);//k每次变化为23和28的公倍数 
		cout<<"Case "<<caseNo<<": the next triple peak occurs in "<<k-d<<" days."<<endl;
	} 
	return 0;
}

【程序47】

分析:1.枚举法假设每一枚硬币为假

           2.同时枚举法假设假硬币是轻是重

 

注意!要用strchr,作用是一个字符是否包含在一个字符串里,

而strstr是操作两个字符串,判断一个字符串是否为另一个的子串,如果将其中一个改成字符会读取乱码(因为根本原因是要读取到 '\0',而单个字符不包含\0 )

char left[3][7] = { {'A','B','C','D'},{'A','B','C','I'},{'A','B','I','J'} };
char right[3][7] = { {'E','F','G','H'},{'E','F','J','K'},{'E','F','G','H'} };
char result[3][7] = { {'E'},{'U'},{'E'} };

bool Isfake(char fake, bool light)
{
    int i = 0;
    char* pL;
    char* pR;
    for (i = 0; i < 3; i++)
    {

        if (light == true)//假设为轻
        {
            pL = left[i];
            pR = right[i];
            switch (result[i][0])
            {
            case 'U':
                if (strchr(pR, fake) == NULL)
                {
                    return false;
                }
                break;


            case 'E':
                if (strchr(pR, fake) != NULL || strchr(pL, fake) != NULL)
                {
                    return false;
                }
                break;



            case 'D':
                if (strchr(pL, fake) == NULL)
                {
                    return false;
                }
                break;

            }

        }
        if (light == false)
        {
            pL = right[i];
            pR = left[i];
            switch (result[i][0])
            {
            case 'U':
                if (strchr(pR, fake) == NULL)
                {
                    return false;
                }
                break;


            case 'E':
                if (strchr(pR, fake) || strchr(pL, fake))
                {
                    return false;
                }
                break;



            case 'D':
                if (strchr(pL, fake) == NULL)
                {
                    return false;
                }
                break;

            }
        }
    }
    return true;

}

int main()
{
    char fake;
    int i;


    for (fake = 'A'; fake <= 'L'; fake++)
    {
        if (Isfake(fake, true))//轻
        {
            printf("%c is the fake coin and it is lightn\n", fake);
            return 0;
        }
        if (Isfake(fake, false))//重
        {
            printf("%c is the fake coin and it is heavy\n", fake);
            return 0;
        }
    }

    return 0;
}

 【程序48】

 

 分析:常规思路是每个开关是否按下的情况都考虑,即2的30次方 种情况,数据过大,会超时,故要思考如何优化代码。

优化如下:

故要考虑的情况只有第一行是否要按,即2的6次方 种情况,因为第一行的情况确定后,后面列的情况是固定的

【程序49】

判断一个点是否在三角形内

int IsContain(double x, double y,
	double x1, double y1,
	double x2, double y2,
	double x3, double y3)
{
	double xx1 = x - x1; double yy1 = y - y1;//MA
	double xx2 = x - x2; double yy2 = y - y2;//MB
	double xx3 = x - x3; double yy3 = y - y3;//MC


	double a = xx1 * yy2 - yy1 * xx2;//MA*MB
	double c = xx2 * yy3 - yy2 * xx3;//MB*MC
	double b = yy1 * xx3 - xx1 * yy3;//MC*MA,注意这个地方调换了顺序

	if (a < 0 && b < 0 && c < 0)
	{
		return 1;
	}
	else if (a > 0 && b > 0 && c > 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}

}
int main()
{
	double x = 1, y = 1;
	double x1 = 0, y1 = 3;
	double x2 = 0, y2 = 0;
	double x3 = 3, y3 = 0;
	int ret = IsContain(x, y, x1, y1, x2, y2, x3, y3);
	if (ret == 1)
	{
		printf("在三角形内");
	}
	else
	{
		printf("不在");
	}
	return 0;
}

【程序50】

【程序51】

#K. 讲笑话
K
传统题
1000ms
256MiB
Description
给你N个数字,每个数字不是1就是-1

问多少个连续的数列和为0

Format
Input
第一行为N, ,N小于等于1e6

第二行为N个用空格隔开的1和-1序列。

Output
总方案数MOD 999999的值

Samples
输入数据 1
9
-1 1 -1 -1  -1  1  1  -1  -1
输出数据 1
8
Limitation
1s, 1024KiB for each test case.

Hint

例如第1个数字到第2个数字

第2个到第7个数字

第6个到第9个数字

它们的和均为0

一共有8种情况

分析:一开始想复杂了,想每次sum==0后,都将pa再指向开头。其实直接一直往后读就好了

#include <stdio.h>
#include <string.h>
int count = 0;

void Count(int* pa)
{
	int* pa2 = pa;
	int sum = 0;
	while (*pa2 != '\0')
	{
		sum += *pa2;
		pa2 += 1;
		if (sum == 0)
			count++;

	}

}
int main()
{
	int arr[9] = { -1,1,-1,-1,-1,1,1,-1,-1 };
	int i;

	for (i = 0; i < 9; i++)
	{
		Count(&arr[i]);
	}
	printf("%d", count);
	return 0;
}

【程序52】

分析:设苹果为a,盘子为p,函数Put(a,p)的作用是算出a个苹果放到p个盘子的放法数量

我们将若干个苹果操作放到若干个盘子里,总的来说有两种情况,

第一种是操作完后没有空盘子剩余,第二种是操作后有空盘子剩余(剩1个,2个或3个等空盘子)

递归的边界条件为,if(a==0 || a==1)  return 1,if(p==0) return 0.

再回到开头讨论a和p的数量,有两种情况

1.当 a < p , Put(a,p) = Put(a,a),因为盘子和苹果完全相同,故有p-a个盘子用不到,不如将其省略,把 “算a个苹果放到p个盘子的放法” 变成 “算a个苹果放到a个盘子的放法”

2.当 a >= p,Put(a,p) = Put(a,p-1) + Put(a-p,p)

 Put(a,p-1)代表有空盘子剩余的情况,至于为什么是p-1,p-1不是只代表了空出1个盘子的情况吗?但放苹果的时候我们可以选择空出2个,3个盘子,这样写是不是错了?其实不是的,因为随着递归层次加深,有一个Put(a,p-1)的分支会将p一直减1,知道p==0,而在这个过程中a不变,所以就计算了了选择空出2个,3个盘子的情况。

Put(a-p,p)代表没有空盘子的情况,那么我们想要实现没有空盘子,就要先往每个盘子里放一个苹果(这是肯定的),然后再计算剩余a-p个苹果放入p个盘子的放法,即Put(a-p,p)

int Put_Count(int a, int p)
{
	if (p == 0)
	{
		return 0;
	}
	if (a == 0 || a == 1)
	{
		return 1;
	}
	if (a < p)
	{
		Put_Count(a, a);
	}
	if (a >= p)
	{
		return  Put_Count(a, p - 1) + Put_Count(a - p, p);
	}
}
int main()
{
	int a = 0;//苹果
	int p = 0;//盘子
	scanf("%d%d", &a,&p);
	printf("%d", Put_Count(a, p));
	return 0;
}

【程序53】

int Len = 0;
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize)
{
    int i, j;
    int count = 0;
    int count1 = 0;
    int count2 = 0;
    int len = 0;
    for (i = 0; i < nums1Size; i++)
    {
     next:
        for (j = 0; j < len; j++)
        {
            if (*(nums1 + i) == *(returnSize + j))
            {
                i += 1;
                
                goto next;
            }
        }
        
        for (j = 0; j < nums1Size; j++)
        {
            if (*(nums1 + i) == *(nums1 + j))
            {
                count1++;
            }
        }

        for (j = 0; j < nums2Size; j++)
        {
            if (*(nums2 + j) == *(nums1 + i))
            {
                count2++;
            }
        }

        if (count1 >= count2)
        {
            
            for (j = 0; j < count2; j++)
            {
                *(returnSize + j + len) = *(nums1 + i);
            }
            len += count2;
            count1 = 0;
            count2 = 0;
        }

        else
        {
            
            for (j = 0; j < count1; j++)
            {
                *(returnSize + j + len) = *(nums1 + i);
            }
            len += count1;
            count1 = 0;
            count2 = 0;
        }
    }
    Len = len;
    return returnSize;


}
int main()
{
    int arr1[] = { 4,9,5 };
    int arr2[] = { 9,4,9,8,4 };
	int sz1 = sizeof(arr1) / sizeof(arr1[0]);
	int sz2 = sizeof(arr2) / sizeof(arr2[0]);
    
	int ret[15] = { 0 };
    intersect(arr1, sz1, arr2, sz2, ret);
    for (int i = 0; i < Len ;i++)
    {
        printf("%d\n", ret[i]);
    }
    
	return 0;
}

【程序54】

int waysToMakeFair(int* nums, int numsSize)
{
    int i, j;
    int c = 0;
    int odd = 0, even = 0;
    int count = 0;
    int arr[10] = {1};
    int* temp = arr;
    temp = (int*)malloc(4 * numsSize);
    for (j = 0; j < numsSize; j++)
    {
        *(temp+j) = *(nums + j);

    }
    //int* temp = arr;
    for (i = 0; i < numsSize; i++)
    {
        for (j = i; j < numsSize - 1; j++)
        {
            *(nums + j) = *(temp + j + 1);
            
        }

        
     *(nums + numsSize - 1) = 0;

        
        
        

        for (j = 0; j < numsSize - 1; j++)
        {

            if (j % 2 == 0)
            {
                even += *(nums + j);

            }

            else
            {
                odd += *(nums + j);

            }
        }

        if (odd == even)
        {
            count++;
            
        }
        odd = 0;
        even = 0;

        for (j = 0; j < numsSize; j++)
        {
            *(nums + j) = *(temp + j);
        }
        
    }
    free(temp);
    temp == NULL;
    return count;
}

int main()
{
    int arr[] = { 1,1,1,1,1};
    int sz = sizeof(arr) / sizeof(arr[0]);
    int ret = waysToMakeFair(arr, sz);
    printf("%d", ret);
    return 0;
}

【程序55】

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
 

提示:

1 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

void Delect(int* nums, int j,int ret)
{
	for (; j + 1 < ret; j++)
	{
		*(nums + j) = *(nums + j + 1);
	}
}
int removeDuplicates(int* nums, int numsSize)
{
	int pmove = 0;
	int temp = 0;
	int i, j = 0;
	int ret = numsSize;
	for (i = 0; i < ret; i++)
	{
		for (j = i; j < ret - 1; j++)
		{
			
			if (*(nums + i) == *(nums + j + 1))
			{
				Delect(nums, j + 1, ret);
				ret -= 1;
				j -= 1;
				numsSize -= 1;
			}
			


		}
	}

	

	return numsSize;
}
int main()
{
	int nums[] = { 0, 0, 1, 1, 1, 2, 2, 3, 3, 4 };
	int* pn = nums;
	int numSize = sizeof(nums) / sizeof(nums[0]);
	
	numSize = removeDuplicates(pn, numSize);
	for (int i = 0; i < numSize; i++)
	{
		printf("%d,", nums[i]);
	}
	return 0;
}

双指针法

int removeDuplicates(int* nums, int numsSize)
{

	if (numsSize == 0) {
		return 0;
	}
	int fast = 1;
	int slow = 1;
	for (; fast < numsSize; fast++)
	{
		if (nums[fast] != nums[fast - 1])
		{
			nums[slow] = nums[fast];
			slow++;
		
		}

	}

	return slow;
}
int main()
{
	int nums[] = { 0,1,  1,  2, 2, 3, 3, 4 };
	int* pn = nums;
	int numSize = sizeof(nums) / sizeof(nums[0]);
	
	numSize = removeDuplicates(pn, numSize);
	for (int i = 0; i < numSize; i++)
	{
		printf("%d,", nums[i]);
	}
	return 0;
}

【程序56】

双指针法,让slow指向链表头,fast指向slow后第k个结点,让slow和fast都向后同步遍历,直到fast为NULL,此时的slow就是答案

【程序57】

思路:

创建head和tail作为合并链表的头和辅助指针,用list1和list2指针对原链表比较各个结点的大小

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


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1==NULL)
    {
        return list2;
    }

    if(list2 == NULL)
    {
        return list1;
    }
    struct ListNode* head = NULL;
    struct ListNode* tail = NULL;
    while(list1 && list2)
    {
        if(list1->val<=list2->val)
        {
            if(head == NULL)
            {
                head = list1;
                tail = list1;
                
            }

            else
            {
                tail->next = list1;
                tail = list1;
            }

            list1 = list1->next;
        }

        else
        {
             if(head == NULL)
            {
                head = list2;
                tail = list2;
                
            }

            else
            {
                tail->next = list2;
                tail = list2;
            }

            list2 = list2->next;
        }

    }

    if(list1)
    {
        tail->next = list1;

    }

    if(list2)
    {
        tail->next = list2;
        
    }

    return head;
}

【程序58】

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    if (headA == null || headB == null) {
            return NULL;
        }
    struct ListNode * pa = headA;
    struct ListNode * pb = headB;
    int lenA,lenB;
    lenA = 0;
    lenB = 0;
    while(headA)
    {
        lenA++;
        headA = headB->next;
    }
    while(headB)
    {
        lenB++;
        headB = headB->next;
    }

    headA = pa;
    headB = pb;

    int d = fabs(lenA-lenB);
    int i = 0;
    if(lenA>=lenB)
    {
        for(i = 0;i<d;i++)
        {
            headA = headA->next;
        }
    }

    else
    {
        for(i = 0;i<d;i++)
        {
            headB = headB->next;
        }
    }

    while(headA&&headB)
    {
        if(headA==headB)
        {
            return headA;
        }
        headA = headA->next;
        headB = headB->next;

    }
    
    return NULL;
}

【程序59】

画菱形

#include <stdio.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    int row = 2 * n - 1;
    int i = 0;
    int j = 0;
    for (i = 1; i <= n; i++)
    {
        for (j = 0; j < n - i; j++)
        {
            printf(" ");
        }
        for (j = 0; j < 2 * i - 1; j++)
        {
            printf("*");
        }
        printf("\n");

    }
    for (i = n; i >=1; i--)
    {
        if (i == n)
        {
            continue;
        }
        for (j = 0; j < n - i; j++)
        {
            printf(" ");
        }
        for (j = 0; j < 2 * i - 1; j++)
        {
            printf("*");
        }
        printf("\n");

    }
    
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值