数组
int a0,a1; -> 这个东西是不能通过循环去引用的,名字是不能拆分的,所有C语言中引入了数组
一、数组定义:
数组是指一组具有相同类型的数据(变量)的集合
int a0,a1…a99; ->如果是用数组定义 —>a[100] 就代表着100个整型数据
二、一维数组
定义的格式
本来->变量的类型[变量的个数] 变量的名字; -> int[10] a;
但是 ->在c语言里面没有int[10]这么一个类型 -> 因此这个[10]就只能放后面
所以数组的定义就是 ->变量的类型 变量的名字[变量的个数]; -> int a[10];
相关要求:
变量的类型:c语言里面合法的类型都可以,如基本类型、构造类型
变量的名字:符合c语言的命名规则就可以了
变量的个数:老版的编译器这个里面只能是常量表达式,发展到现在我们可以用一个有确定值的变量来给这给 个数
注意:如果你是用变量去定义的数组,你是不能初始化的
例子:
int a[5];
//意思就是有5个相同int的变量被定义出来了
//你要用这5个变量 直接用这个a就可以了
//typeof -> 求一个变量的类型
//typeof(a) -> int[5]
int * p = a;
//typeof(p) -> int *
//int[5] int*在很大意义上面是一样的,但是也不一样 int*没有范围,int[5]是确定了范围
数组初始化:
- 数组定义完之后我们对其全部初始化
int a[5] = {1,2,3,4,5}; //一定不要超标
char name[10] = "abcdefghi"; //字符串后面必有\0
如果我想对这个数组全部初始化,定义数组的时候可以不用给个数,编译器可以猜多少个元素
int a[] = {1,2,3,4,5};
//与int a[5] = {1,2,3,4,5};一模一样
- 数组可以部分初始化,后面没有初始化的部分会全部初始化为0
int a[5] = {1,2,3}; // a[3] == 0 , a[4] == 0
3.数组不初始化里面的值是未知的,很多时候我们可以对一个数组进行清零
int a[5] = {0};
*注意:
int a[5] = {0};
只有在定义的时候 也就是初始化的时候才能这么干
经过不知名的操作之后, 这个a里面就有了各种各样的值
这个时候我又想对这个数组清零
---->只能循环
memset ->实际上也是用循环来实现的
数组在内存中的存放:
引言:
数组定义出来了,要想使用,我们还需要知道这个数组的地址,也就是这几个数据在内存里面的存放
数组的内存分布:
数组定义之后 ,里面的每个元素是在连续的地址空间里面,第2个紧挨着第一个存放就可以了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p5oqTtGf-1625710547555)(E:\粤嵌学习笔记\C语言\数组的存放.png)]
一维数组元素的引用:
用数组的下标去引用这个数组
数组名[下标]; 下标从0开始 ,小于数组的个数
示例:
int a[10];
a[0] ->数组的第一个元素
a[1] ->数组的第二个元素
…
a[9] ->数组的第十个元素,也就是最后一个
一维数组元素的使用:
数组元素用的时候跟一个变量是一模一样的,变量怎么用那么数组的元素就怎么用
示例:
int b;
b = 1024;
int a[10];
a[0] = 1024;
a[9] = 1025;
跟普通变量一样 , 符合左值与右值的规则,因此数组的元素一样的是可以取地址的
题目:打印数组
定义一个数组 手动输入里面的值 用循环,并打印出这个数组
int a[10];
int i;
for(i = 0;i < 10;i++)
{
scanf("%d",&a[i]);
}
for(i = 0;i < 10;i++)
{
printf("%d\t",a[i]);
}
printf("\n");
数组名的含义:
例:
int a[10]; 变量的个数 ->代表着相同类的数据的个数
a有两个含义:
1.数组首地址,这个时候相当于一个指针,指向数组首地址
2.变量 ,代表整个数组
int main()
{
int a[10];
int *p = a;
sizeof(a); //40,因为a就是一个变量,代表整个数组。sizeof(a) -> sizeof(int[10])
sizeof(p); //4/8
}
//sizeof(数组名):返回数组所有元素占有的内存空间字节数。
//sizeof(指针) :返回计算机系统的地址字节数,如果是32位系统,返回4,64位系统返回8
int a[10];
scanf("%d",&a); //不可以
//typeof(a) -> int[10]
//typeof(&a) -> typeof(&int[10]) -> int[10] * -> int **
// 表明&a是整个数组的地址,整个数组的地址是代表的整个数组
// 而数组的首地址代表数组第一个元素
a + 1 // 代表的是第二个元素
&a + 1 // 代表跳过这个数组
++a; //不可以,a本身不能变
scanf("%d",a); a -> &a[0]
这么写是可以的 a代表的就是第一个元素 并且它就是一个地址
*重点注意:
a代表的是首地址 , 同时也是代表的第一个元素的地址
因此左值右值都可以
* a = 1024; <-> a[0] = 1024
++a,a++是不行的
a + 1是可以的
核心思维:虽说a是个首地址 并且a代表的是第一个元素的地址
并且a本身就是一个变量
但是a由于代表的是整个地址 如果你改变了那么这个数组就变了
因此a是不能改变的
因此 a =a + 1也不行
#include<stdio.h>
int main()
{
char a[5]={'A','B','C','D'};
char (*p3)[10] = &a;
char *p4 = a;
printf("%p\n",p3);
printf("%p\n",p3+1);
printf("%p\n",p4);
printf("%p\n",p4+1);
return 0;
}
/*运行结果:
0x7ffe10adcd23
0x7ffe10adcd2d
0x7ffe10adcd23
0x7ffe10adcd24
*/
/*
a:代表数组首个元素的地址
&a:代表整个数值的首地址
值是相同的,但意义不同
*/
三、字符串的长度(strlen)和数组的大小(sizeof)
数组里面有一个比较特殊的存在 ,字符串数组,这个里面涉及两个概念,字符串长度和数组的大小
字符串长度不等于字符串数组大小
字符串数组所能容纳下的的最长的字符串长度为 = 字符串数组大小 - 1
因为还有一个字节需要用来存放“\0”
//例1:
char name[16] = "penglei";
printf("%d\n",sizeof(name)); //求数组大小,输出16,表示数组大小为16字节
printf("%d\n",strlen(name)); //求字符串长度,遇到\0结束,输出结果为7
char name[] = "penglei\0henshuai";
printf("%d\n",sizeof(name)); //求数组大小,输出17,字符串末尾一定是以\0结尾
printf("%d\n",strlen(name)); //求字符串长度,遇到\0结束,输出结果为7
数组在分配空间的时候不是看谁先定义的
是看谁小一些 , 谁就在前面 , 并且连续开辟
%s 和strlen都是需要看到\0才会结束的
//例2:
int i;
char name[3] = {'a','b','c'};
printf("%d\n",sizeof(name)); //求数组大小,输出3,表示数组大小为3字节
printf("%d\n",strlen(name)); //结果未知,数组后面是多少都不知道,不知道什么时候能遇到\0结束
char name[3];
char name1[10];
for(i=0;i<7;i++)
{
scanf("%c",&name[i]); //-> {'a','b','c','d','e','f','g'}
}
name1[0] = 'h';
printf("%s\n",name); // 输出结果->abc
printf("%s\n",name1); //输出结果->hefg
注意:
以下代码虽说有一定的问题, 但是里面说明了很多的问题
#include <stdio.h>
#include <string.h>
//这个代码实质是有问题的 写到这里只是为了说明数组存放、越界等问题
int main()
{
char name1[10] = {0};
char name[2] = {0};
char name2[3] = {0};
int i = 0;
for(;i < 7;i++)//你已经越界了
{
scanf("%c",&name[i]); //-> {'a','b','c','d','e','f','g'}
}
name1[0] = 'h';
/*name1 = "h"; c语言里面字符串是不能直接赋值的,我们想要赋值字符串 只能一个字节一个字节的赋值
只有在初始化的时候才能直接等于*/
char * p;
p = "hehe"; //这个hehe会放入一个叫.rodata的空间
//放入这个空间之后 返回一个首地址给p
printf("%d %s\n",(int)strlen(name),name); //这里也有越界
printf("%d %s\n",(int)strlen(name1),name1);
printf("%d %s\n",(int)strlen(name2),name2);
printf("%s\n",p);
return 0;
}
四、一维数组相关题目
题目:求数组和、最大值、最小值
1.求一个数组的和,并且打印出最大的与最小的
//求一个数组的和,并打印出这个数组中的最大最小值
#include<stdio.h>
int main()
{
int a[5]={3,2,6,1,7};
int sum = 0,i,max = a[0],min = a[0];
for(i = 0;i<5;i++)
{
if(max<a[i])
{
max = a[i];
}
if(min>a[i])
{
min = a[i];
}
sum += a[i];
}
printf("sum = %d\n",sum);
printf("最大值为:%d,最小值为:%d\n",max,min);
return 0;
}
题目:打印斐波拉契数列
2.斐波拉契数列,打印前20项和前20项的和
1 1 2 3 5 8 13 … 即后一项等于前两项之和
//斐波拉契数列,打印前20项和前20项的和
#include<stdio.h>
int main()
{
int i,j,sum = 2;
int a[20] = {1,1};
for(i = 2;i < 20;i++)
{
a[i] = a[i-1] + a[i-2];
sum += a[i];
}
for(j = 0;j < 20;j++)
{
printf("%d\t",a[j]);
}
printf("\nsum = %d\n",sum);
return 0;
}
题目:判断数列是否递增
3 .给定一个数列,判断这个数列是否为递增, 如果是 打印yes 否则打印no
//给定一个数列,判断这个数列是否为递增,是的话打印yes,否则打印no
#include<stdio.h>
int main()
{
int i;
int a[6] = {2,3,4,5,6,7};
for(i = 0;i < 5;i++)
{
if(a[i]>a[i+1])
{
printf("no\n");
break;
}
}
if(i == 5)
printf("yes\n");
return 0;
}
/*
错误点:for(i = 0;i < 6;i++)
for循环里面的判断条件应该是i < 5,而不是i < 6,
要考虑到a[i+1]不能越界。
*/
/*老师代码:不用break;直接用return 0;结束主函数。
int i;
int a[6] = {2,3,4,5,6,7};
for(i = 0;i < 5;i++)
{
if(a[i]>a[i+1])
{
printf("no\n");
return 0;
}
}
printf("yes\n");
*/
题目:有序数列查找元素
4.给定一个有序的数列,查找其中的一个元素
1 遍历 -> 一个个找
2 二分法 -> 折中查找
//给定一个有序数列,查找其中一个元素
//方法1:遍历 -> 一个个找
#include<stdio.h>
int main()
{
int i,n;
int a[6] = {1,2,5,7,8,9};
printf("请输入想要查找的元素:");
scanf("%d",&n);
for(i = 0;i < 6;i++)
{
if(n == a[i])
{
printf("a[%d]=%d\n",i,n);
return 0;
}
}
printf("没有找到该元素!\n");
}
//方法2:二分法 -> 折中查找
#include<stdio.h>
int main()
{
int a[6]={1,2,5,7,8,9};
int left = 0,right = 5,mid,n;
printf("请输入想要查找的元素:");
scanf("%d",&n);
while(1)
{
mid = (left+right)/2;
if((right == left + 1)||(right == left))
{
if(n == a[left])
{
printf("a[%d] = %d\n",left,n);
return 0;
}
else if(n == a[right])
{
printf("a[%d] = %d\n",right,n);
return 0;
}
else
{
printf("查询无果!\n");
return 0;
}
}
if(n == a[mid])
{
printf("a[%d] = %d\n",mid,n);
return 0;
}
if(n > a[mid])
{
left = mid + 1;
}
if(n < a[mid])
{
right = mid - 1;
}
}
}
题目:冒泡排序
冒泡 -> 一趟冒泡会将最大值移到最后
只要前面的一个值比后面的一个值大 ,那么就换位置
//冒泡排序
#include<stdio.h>
int main()
{
int a[10]={2,5,2,5,32,4,6,9,66,1};
int i,j,k;
for(i = 0;i<9;i++)
{
for(j = i+1;j<10;j++)
{
if(a[i]>a[j])
{
a[i] = a[i]^a[j];
a[j] = a[i]^a[j];
a[i] = a[i]^a[j];
}
}
}
for(k = 0;k<10;k++)
{
printf("%d\t",a[k]);
}
printf("\n");
return 0;
}
题目:选择排序
选择排序 -> 一趟找出没有排好的最大值 , 放到没有排好的最后面去
我们需要将最大值的下标保存下来
//选择排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(末尾位置),然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾(开头)。
//选择排序跑一趟只交换一次位置,和冒泡排序不同的地方是冒泡排序是边比边交换
#include<stdio.h>
int main()
{
int a[10]={2,5,2,5,32,4,6,9,66,1};
int i,j,k,max = 0; //max标记无序序列最大值下标
for(i = 9;i>0;i--)
{
for(j = 0;j<=i;j++)
{
if(a[max]<a[j])
max = j;
}
a[max] = a[max]^a[i];
a[i] = a[max]^a[i];
a[max] = a[max]^a[i];
}
for(k = 0;k<10;k++)
{
printf("%d\t",a[k]);
}
printf("\n");
return 0;
}
题目:插入排序
//插入排序:将一个记录插入到已经排好序的有序表中,
//从而形成一个新的、记录数增1的有序表。
//初始时已排好的序列为a[0]一个数,a[1]和a[0]比较,大不变,小,交换位置。
#include<stdio.h>
int main()
{
int i,j,k,num;
int a[6]={5};
printf("请输入5个数:");
for(i = 1;i<6;i++) //外循环,循环插入5个数
{
scanf("%d",&a[i]);
for(j = 0;j<i;j++) //内循环,对插入的数排位置
{
if(a[i]<a[j])
{
//移位
num = a[i];
k = i;
while (k >= j+1)
{
a[k] = a[k-1];
--k;
}
a[j] = num;
break;
}
}
}
for(k=0;k<6;k++)
{
printf("%d\t",a[k]);
}
printf("\n");
return 0;
}
题目:随机排序
需将 1 ~ 100 随机的分布到100个元素的数组里面去,且数组里面的数是不会重复的
// 需求 1 ~ 100 随机的分布到100个元素的数组里面去
// 数组里面的数是不会重复的
/* 代码思想:将1~100随机插入到arr[100]中,add[100]记录下
arr[100]中0的下标,即未被插入数字的空位下标*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int i,j,k,num = 100; //num:剩余0(空位)的个数
int arr[100]={0};
int add[100]={0};
srand((int)time(NULL));
for(i = 1;i<=100;i++) //循环将1~100随机插入arr[100]中
{
arr[add[rand()%num]] = i; //随机位置插入i
--num;
for(j = 0,k = 0;k<100;k++) //插完一个数后,遍历arr[100]更新add[100]
{
if(0 == arr[k])
{
add[j] = k;
j++;
}
}
}
for(i = 0;i<100;i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
return 0;
}
//需求 1 ~ 100 随机的分布到100个元素的数组里面去
//数组里面的数是不会重复的
/*代码思想:先将1~100按顺序插入数组arr[100]中,
再将每一个数与下标为1~99的随机一个数交换*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int i,j,temp;
int arr[100]={0};
srand((int)time(NULL));
for(i = 1;i<=100;i++)
{
arr[i-1] = i;
}
for(i = 99;i>=0;i--)
{
j = rand()%100;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for(i = 0;i<100;i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
}
/*测试结果:
随机交换位置后出现数字0
原因:源代码
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
存在问题:
i有可能等于j,相等就会出现
a[i]=a[i]^a[i] -> a[i] = 0;
a[j]=a[j]^a[j] -> a[j] = 0;
a[i]=0^0 -> a[i] = 0;
设a[i]的值是6,6^6 等于0
a[i]原有的值就丢失了,变成0了
考虑那种更公平:
(1)将每一个数与下标为0~99,包括它自己本身的值进行随机交换
(2)从最后一个数开始,每一个数与除自己本身的前面的数进行随机交换位置
*/
题目:找数组中第二大的值
//找一个数组中的第二大的值
//更新最大值的同时将没有更新之前的最大值换到第二大就可以了
//如果有一个值比第二大的大 但是比第一大的小 那么直接更新第二大的
#include<stdio.h>
int main()
{
int a[5]={3,5,8,6,4};
int i,max=a[0],max2=a[0];
for(i=1;i<5;i++)
{
if(max2<a[i])
{
if(max<a[i])
{
max2 = max;
max = a[i];
}
else
max2 = a[i];
}
}
printf("数组中第二大的值为:%d\n",max2);
return 0;
}
题目:将一个数组中的负数放到正数的前面
//将一个数组中的负数放到正数的前面
#include<stdio.h>
int main()
{
int a[5]={-1,4,7,-5,9};
int i,j,k;
for(i = 0;i<5;i++)
{
if(a[i]>0)
{
k = i;
break;
}
}
while(i<4)
{
if(a[i+1]<0)
{
a[k]=a[k]^a[i+1];
a[i+1]=a[k]^a[i+1];
a[k]=a[k]^a[i+1];
++k;
}
i++;
}
for(j=0;j<5;j++)
{
printf("%d\t",a[j]);
}
printf("\n");
return 0;
}
五、 多维数组
二维数组定义:
数据类型 数组名 [行的大小] [列的大小]
如:
int arr[3][5];
行和列的大小跟一维数组里面的个数的给定方式一样
一般我们给常数表达式,如果你要用变量也是可以的
但是用了变量你就不能初始化,而且你用的变量必须要有确定的值
二维数组在内存的分布
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6HEaMop3-1625710547557)(E:\粤嵌学习笔记\C语言\二维数组内存.png)]
二维数组的初始化
1 .我们可以分行对二维数组进行初始化
int a[2][3] = {
{1,2,3},
{4,5,6}
};
2.我们可以将上述的这种形式写在一个或括号里面
int a[2][3] = {1,2,3,4,5,6};
3.部分初始化 剩余没有初始化的会自动置0
int a[2][3] = {
{1,2}, //第一行初始化2个 第三个为0
{4,5} //第二行初始化2个 第三个为0
};
int a[2][3] = {1,2,4,5}; //-> 第一行全部初始化 1 2 4
//第二行只会初始化1个 5 0 0
4 .如果对于一个二维数组全部初始化 那么我们可以省略行的个数,但是列是不能省略的
int a[][3] = {
{1,2,3},
{4,5,6}
};
//或者
int a[][3] = {
1,2,3,4,5,6
};
//或者
char name[][16] = {
"penglei",
"henshuai",
.....
};
二维数组元素的引用
1.单个元素引用 -> 数组名[行] [列] (行列的下标都是从0开始)
2.想用一行数据 -> 数组名[行] -> 数组名[行]所代表的就是一行数据
既然二维数组本质上就是一维数组 ,那么我们也可以搞一个指针直接去用一里面单个的元素
a[0] ->代表的第一行, 就是第一行的首地址
六、二维数组相关题目
题目:二维数组最大最小值
1.求一个二维数组的最大值与最小值,以及打印出数组的和
//求一个二维数组的最大值与最小值,以及打印出数组的和
#include<stdio.h>
void max_min_sum(int arr[2][3], int a, int b);
int main()
{
int arr[2][3]={4,5,2,6,2,3};
max_min_sum(arr, 2,3);
return 0;
}
void max_min_sum(int arr[2][3],int a,int b)
{
int i,j,max = arr[0][0],min = arr[0][0],sum = 0;
for(i = 0;i<a;i++)
{
for(j = 0;j<b;j++)
{
sum += arr[i][j];
if(max < arr[i][j])
{
max = arr[i][j];
}
if(min > arr[i][j])
{
min = arr[i][j];
}
}
}
printf("max = %d,min = %d,sum = %d\n",max,min,sum);
}
题目:求和最大的行和列
2.求一个二维数组里面元素之和最大的那一列和那一行
//求一个二维数组里面元素之和最大的那一列和那一行
#include<stdio.h>
int main()
{
int arr[3][3]={2,4,5,1,6,3,2,9,3};
int i,j,r_max,c_max,sum,row,col;
for(i = 0;i<3;i++) //行求最大和并记录下标
{
sum = 0; //重置和
for(j = 0;j<3;j++) //求i行的和
{
sum += arr[i][j];
}
if(r_max<sum) //把行最大和赋值给r_max
{
r_max = sum;
row = i;
}
}
for(i = 0;i<3;i++) //列求最大和并记录下标
{
sum = 0; //重置和
for(j = 0;j<3;j++) //求i行的和
{
sum += arr[j][i];
}
if(c_max<sum) //把行最大和赋值给c_max
{
c_max = sum;
col = i;
}
}
printf("第%d行和最大,值为%d,第%d列和最大,值为%d\n,",row,r_max,col,c_max);
return 0;
}
题目:求山顶元素
3.山顶元素:比左右上下都大的就是山顶元素
方法1:可以,但不够简单
//求山顶元素
//山顶元素:比左右上下都大的就是山顶元素
//该代码思路:把需要判断的数组放入一个比它大一圈数组(解决接下来判断涉及到的越界问题),
//使得需要判断的数组周围都是0
#include<stdio.h>
int main()
{
int i,j;
int a[3][3]={5,2,6,4,13,55,4,3,9};
int b[5][5]={0};
for(i = 1;i<4;i++)
{
for(j = 1;j<4;j++)
{
b[i][j] = a[i-1][j-1];
}
}
for(i = 1;i<4;i++)
{
for(j = 1;j<4;j++)
{
if(b[i][j]>b[i-1][j]&&b[i][j]>b[i+1][j]&&b[i][j]>b[i][j-1]&&b[i][j]>b[i][j+1])
printf("%d为山顶元素\n",b[i][j]);
}
}
return 0;
}
/*该代码对存在负数的数组不成立
改进:先遍历数组a,找出数组a中的最小值,再将最小值减1作为b的初始化值*/
方法二:简单高效
//题目:求山顶元素。老师代码:使用惰性运算
//思路:if里面写4个条件,依次判断元素是否大于上下左右的值。
/*
条件1:左边有值||元素>左边元素 ->左边有值才会判断右边
条件2:右边有值||元素>右边元素
....
最后:条件1&&条件2&&...
*/
#include<stdio.h>
int main()
{
int i,j;
int a[3][4]={45,5,2,12,7,8,34,56,22,11,4,1};
for(i = 0;i<3;i++)
{
for(j = 0;j<4;j++)
{
if((i == 0||a[i][j]>a[i-1][j])&&(i == 2||a[i][j]>a[i+1][j])
&&(j == 0||a[i][j]>a[i][j-1])&&(j == 3||a[i][j]>a[i][j+1]))
printf("%d是山顶元素\n",a[i][j]);
}
}
return 0;
}
/*班上大多数同学使用的方法:
用了9个if,把每种情况都下该做哪几步,都写出来了*/
题目:输出杨辉三角
4.输出杨辉三角的前10行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
…
//输出杨辉三角的前10行
//方法1:使用一维数组,每更新一次数组输出一次
#include<stdio.h>
int main()
{
int a[10]={1,1};
int i,j,k;
for(i = 0;i<10;i++)
{
a[i] = 1;
for(k = i-1;k>0;k--)
{
a[k] = a[k]+a[k-1];
}
for(j = 0;j<=i;j++)
{
printf("%d\t",a[j]);
}
printf("\n");
}
return 0;
}
//杨辉三角输出
//方法2:使用二维数组,依次给每一个数组元素赋值,
//每次输出一行的前(行号+1)个元素
#include<stdio.h>
int main()
{
int i,j;
int a[10][10];
printf("1\t");
printf("\n");
for(i=1;i<10;i++)
{
for(j = 0;j<=i;j++)
{
if(0 == j || i == j)
{
a[i][0] = a[i][i] = 1;
}
else
{
a[i][j] = a[i-1][j] + a[i-1][j-1];
}
printf("%d\t",a[i][j]);
}
printf("\n");
}
return 0;
}
题目:高数据占座问题
5.高数据占座问题
有一个人叫高数据 它要给它和它的2个室友(3个人)去占座位
它有一个习惯 它不能和它的室友分开,并且不能前后坐
只能三个人连在一起 并且座位已经有一些被占了
写代码去求一下他们有多少种占法
自己去给这个座位
//高数据占座问题
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
srand((int)time(NULL));
int i,num = 0;
int a[100] = {0}; //100个座位
for(i = 0;i<rand()%50;i++) //随机占用了随机个座位
{
a[rand()%100] = 1;
}
for(i = 0;i<100;i++)
{
if(a[i]==0 && a[i+1]==0 && a[i+2]==0) //判断是否有连续的三个空位
{
num++;
}
}
printf("%d\n",num);
return 0;
}
题目:最大子数组和
6.求一个一维数组最大子数组(连续的)的和
2 -1 -3 4 5 -8 -9 10 11 -2
最大的子数组为
10 11 和为21
1 .暴力破解: 列觉所有的情况, 得出最大值
2 .sum只要加到了小于0的情况, 那么直接等于0
#include <stdio.h>
int main()
{
int a[10] = {-10,3,3,-4,5,-3,0,-20,-30,10000};
int sum = a[0];
int sum_max = sum;
int i = 0;
for( ;i < 10;i++)
{
sum += a[i];
if(sum < 0)
{
sum = 0;
}
if(sum_max < sum)
{
sum_max = sum;//更新max
}
}
if(sum_max <= 0)
{
sum_max = a[0];
//遍历最大值就可以了
for(i = 0 ;i < 10;i++)
{
if(sum_max < a[i])
{
sum_max = a[i];
}
}
}
printf("%d\n",sum_max);
return 0;
}
- 其他方法
//求一个一维数组最大子数组(连续的)的和
//例:2 -1 -3 4 5 -8 -9 10 -2 12 最大的子数组为10 -2 12 和为20
#include<stdio.h>
int main()
{
int a[10]={2,-1,-3,4,5,-8,-9,10,-2,12};
int i,j,sum = 0,max_sum = 0,flag_i,flag_j;
for(i = 0;i<10;i++) //外循环
{
sum = 0;
for(j = i;j<10;j++) //内循环
{
sum += a[j];
if(sum>max_sum)
{
max_sum = sum;
flag_i = i; //记录和最大的数组字段开始位置
flag_j = j; //记录和最大的数组字段结束位置
}
else if(sum<0)
{
i = j+1;
break;
}
}
}
printf("最大子数组为:");
for(i = flag_i;i<=flag_j;i++)
{
printf("%d\t",a[i]);
}
printf("\n");
printf("和为:%d\n",max_sum);
return 0;
}
/*
原来的代码:
思路:只要遇到一个负数,就认为前面这段子数组不是最大子数组段,也就是
说我之前认为的最大子数组字段里面是不能有负数的,以下代码实现的寻找数组
中和最大的正数子数组段。
for(i = 0;i<10;i++) //外循环
{
sum = 0;
for(j = i;j<10;j++) //内循环
{
flag_i = i;
if(sum<(sum + a[j]))
{
sum = sum + a[j];
flag_j = j;
}
else
{
i = j + 1;
break;
}
}
}
*/