C语言数组

Posted on 2019-07-07 19:30  不叫柒桓叶  阅读(2383)  评论(0编辑  收藏  举报

引用:

int a,b,c,d,......

int sum

 

=>

定义一类或一组变量

 

数组

 

1.数组是什么?

数组是一组具有相同类型的数据(变量)的集合

 

C语言中数组:

一维数组

二维数组

三维数组

...

 

其实,C语言中只有一维数组

 

 

2,一维数组

2.1 定义格式

类型说明符 数组名[整型表达式] {={初始化列表}};

{}: 可要可不要

 

"类型说明符":指定数组元素的类型,任意C语言合法的类型都可以

数组名”:对象的名字,命名要符合C语言标识符的规定

整型表达式” :指定数组中元素的个数,一般为常量表达式

eg:

#define N 3

 

int a[10];//定义了一个数组,数组名a,里面有10int型元素

typeof(a)  =>一个具有10int元素的数组类型 int[10]

 

char b[10];

typeof(b)  => 一个具有10char元素的数组类型 char[10]

 

 

int c;//在程序运行的时候,为c分配4个字节的空间

 

在程序运行的时候,为a分配多大的空间?

 10int =40个字节

 

sizeof(a) =>40

 

2.2 一维数组在内存中的存放

在连续的地址空间中,从低地址到高地址依次存放数组中的每个元素。

意思:第二个元素只能紧跟着第一个元素后面存放

 

int a[10];

0x0001  -> 第一个元素

0x0005  -> 第二个元素

....

 

2.3一维数组元素的引用

int a[10];

 

引用方式:

数组名[下标];//C语言的下标是从0开始

 

a[0] 数组中第一个元素

...

 

a[9]

 

 

引用数组元素a[i] 和引用普通变量是一样的,都有左值和右值,还可以取地址

eg:

 

int  b;

b = 1024;

a[0] = 1024;//表示数组元素a[0]的地址

b = a[0]; //表示数组元素a[0]的值

 

练习:

定义一个整型数组,数组中有10个元素。从键盘上输入值来给元素赋值

然后把整个数组输出

 

int a[10];

 

for(i = 0; i<10;i++)

{

scanf("%d",&a[i]);

}

 

printf("%d\n",a);

 

2.4 一维数组的初始化

初值是存在一对花括号中

 

(1)数组元素全部初始化

int a[10] = {1,2,3,4,5,6,7,8,9,10};

 

eg:

int a[10];

a[10] = {1,2,3,4,5,6,7,8,9,10};//error

 

(2)可以只对部分元素初始化,后面的元素自动初始化为0

 

int a[10] = {1,2,3};

 

把整个数组初始化为0

int a[10] = {0};

 

(3)如果对全部元素初始化,那么在定义数组的时候,可以不指定数组的长度

why?

int a[] = {1,2,3};

 

 

☆☆

char s[] = {'a','b','c'};

=>数组s里面有3个元素

 

printf("%s",s);

 

char s1[10] = {'a','b','c'};

printf("%s",s1);

 

“字符串长度” :就是从一个起始地址的内容开始找,找到第一个\0为止

前面有多少个字符,那就是字符串的长度

 

数组的长度 :数组有多少个元素

 

eg:

int a[10];

sizeof(a)/sizeof(a[0])

 

字符数组的大小:这个数组所占空间的大小

sizeof(s) => 3

 

sizeof(s1) => 10

 

 

练习:

1)求一个一维数组(int)中元素之和

最大值,最小值 3.c

"遍历" :对某个对象中每个元素访问且仅访问一次

 

int x,i,max,min,sum;

scanf("%d",&x);

int a[x];

max = a[0];

min = a[0];

for(i = 0;i <x;i++)

{

scanf("%d",&a[i]);

}

 

for(i = 0; i < x;i++)

{

if(max < a[i])

{

max = a[i];

}

if(min > a[i])

{

min = a[i];

}

}

printf("max = %d,min = %d\n",max,min);

 

2Fibonacci(斐波那契数列前20项之和)

1 1 2 3 5 8 13 21 ...

 

从第三项开始,每一项都是前面两项之和

int Fi[20] = {1,1};

int sum = 2;

 

Fi[2] = Fi[1] +Fi[0];

sum += Fi[2];

 

Fi[3] = Fi[2] +Fi[1];

sum += Fi[3];

...

for(i = 2;i < 20;i++)

{

Fi[i] = Fi[i-1] +Fi[i-2];

sum += Fi[i];

}

 

 

 

3)给定一个一维数组(int),判断是否为递增数组

a[0] < a[1] <a[2] <a[3]...a[n-1]

 

int x,i;

scanf("%d",&x);

int a[x];

int flag = 1;//递增标志位 1 :递增 ,0 :非递增

for(i = 0;i <x;i++)

{

scanf("%d",&a[i]);

}

 

for(i = 0;i < x-1;i++)

{

if(a[i] >= a[i+1] )

{

flag = 0;

break;

}

}

/*

if(i == x-1)

{

printf("yes\n");

}

*/

if(flag)

{

printf("yes\n");

}

 

(4)在一个给定的升序的一维数组中,查找一个元素

int a[10];

 

查找数组a中是否有元素x,有就打印yes,没有就打印no

 

二分法/二分查找法

代码

int find(int n,int a[],int l)
{
int low=0;
int high=l-1;
int middle=0;
while(low<high)
{
middle=(low+high)>>1;
if(n==a[middle])
{
printf("%d,%d",n,middle);
return 1;

 

}
else if(n>a[middle])
low=middle+1;

else
high=middle-1;

}

 

return 0;

}

 

int main()

{
int a[]={2,3,5,6,7,8,9,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60};
int l=sizeof(a)/sizeof(a[0]);
int i=0,n;
printf("arry content");
for(i=0;i<l;i++)
{
if(i%8==0)
printf("\n");
printf("%4d",a[i]);



}
printf("\nseach n is ");
scanf("%d",&n);
if(!find(n,a,l))
printf("not fond");
return 0;

}

 

 

二分查找的基本思想是:(设R[low..high]是当前的查找区间)
 1)首先确定该区间的中点位置:
                 
 2)然后将待查的K值与R[mid].key比较:若相等,则查找成功并返回此位置,否则须确定新的查找区间,继续二分查找,具体方法如下:
     R[mid].key>K,则由表的有序性可知R[mid..n].keys均大于K,因此若表中存在关键字等于K的结点,则该结点必定是在位置mid左边的子表R[1..mid-1]中,故新的查找区间是左子表R[1..mid-1]
     类似地,若R[mid].key<K,则要查找的K必在mid的右子表R[mid+1..n]中,即新的查找区间是右子表R[mid+1..n]。下一次查找是针对新的查找区间进行的。
     因此,从初始的查找区间R[1..n]开始,每经过一次与当前查找区间的中点位置上的结点关键字的比较,就可确定查找是否成功,不成功则当前的查找区间就缩小一半。这一过程重复直至找到关键字为K的结点,或者直至当前的查找区间为空(即查找失败)时为止。

 

二分查找算法
    int BinSearch(SeqList RKeyType K)
      { //在有序表R[1..n]中进行二分查找,成功时返回结点的位置,失败时返回零
        int low=1high=nmid//置当前查找区间上、下界的初值
        while(low<=high){ //当前查找区间R[low..high]非空
          mid=(low+high)/2
          if(R[mid].key==K) return mid//查找成功返回
          if(R[mid].kdy>K)
             high=mid-1; //继续在R[low..mid-1]中查找
          else
             low=mid+1//继续在R[mid+1..high]中查找
         }
        return 0//low>high时表示查找区间为空,查找失败
       } //BinSeareh

 

二分查找的优点和缺点
  虽然二分查找的效率高,但是要将表按关键字排序。而排序本身是一种很费时的运算。既使采用高效率的排序方法也要花费O(nlgn)的时间。
  二分查找只适用顺序存储结构。为保持表的有序性,在顺序结构里插入和删除都必须移动大量的结点。因此,二分查找特别适用于那种一经建立就很少改动、而又经常需要查找的线性表。
  对那些查找少而又经常需要改动的线性表,可采用链表作存储结构,进行顺序查找。链表上无法实现二分查找。

 

 

a:1 2 3 5 6 8 9    x = 4

 

l = 0

r = 6

mid = 3

 

=>

l = 0

r = mid-1 = 2

mid = 1

 

=>l = mid+1 = 2

  r = 2

  mid = 2

  

 =>l = mid+1 = 3

r = 2

 

int a[n];

int l = 0,r = n-1;

 

while(l <= r)

{

mid = (l+r)/2;//范围[l,r]中间元素的下标

 

if(a[mid] == x)

{

break;

}

else if(a[mid] > x)

{

r = mid-1;

}

else

{

l = mid+1;

}

}

 

 

作业:

因式分解

90 = 2*3*3*5

15

 

1)将一个一维数组(int)排序

 

2)一个一维数组中有正有负,写一个程序,把数组中负数放在正数的前面

 

3)求一个一维数组中第二大的元素

 

考虑有重复的元素

 

4)一维数组的插入排序

 

 

 

答案

 

作业:

0因式分解

90 = 2*3*3*5

15

算法1

sum=1;

num1 = num;

for(i=2i<num)

{

if(num%i==0)

{

sum*=i;

a[x]=i;

x++;

num/=i;

}

else

i++;

if(sum==num1)

break;

}

 

算法2

90

[2,n/2]

 

for(i = 2;i <= n/2;i++)

{

while(n%i == 0)

{

printf("%d*",i);

n /= i;

}

}

printf("%d\n",n);

90

 

1)将一个一维数组(int)排序

冒泡排序:

两两比较,大的往后移

 

9 7 8 4 2

7 9 8 4 2

7 8 9 4 2

7 8 4 9 2

7 8 4 2 9

 

if(a[0] > a[1])

{

a[0] <-> a[1]

}

if(a[1] > a[2])

{

a[1] <-> a[2]

}

...

if(a[i] > a[i+1])

{

a[i] <-> a[i+1]

}

 

for(i = 0;i < N-1;i++)

{

if(a[i] > a[i+1])

{

a[i] <-> a[i+1]

}

}//一趟冒泡

 

for(j = 0;j < N;j++)

{

for(i = 0;i < N-j;i++)

{

if(a[i] > a[i+1])

{

a[i] <-> a[i+1]

}

}

}

 

选择排序:

从待排序的数组中,选择最大的那个元素与最后面的那个元素进行交换

 

4 8 2 6 3

 

i = 0;

if(a[1] < a[0])

{

a[1] <-> a[0]

}

 

if(a[2] < a[0])

{

a[1] <-> a[0]

}

if(a[N-1] < a[0])

{

a[1] <-> a[0]

}

====

for(i = 0;i < N;i++)

{

for(j = i+1;j < N;j++)

{

if(a[j] < a[i])

{

a[1] <-> a[0]

}

}

}

 

===========

 

2)一个一维数组中有正有负,写一个程序,把数组中负数放在正数的前面

-3 4 9 -2 -3

=>

int next = 0;

for(i = 0;i < N;i++)

{

if(a[i] < 0)

{

a[next] <->a[i]

 

next++;

}

}

 

 

3)求一个一维数组中第二大的元素

 

考虑有重复的元素

 

9 9 8 8 8

 

max = a[0];

second = [1];

 

for(i =0;i < M;i++)

{

if(a[i] > max)

{

second = max;

max = a[i];

}

}

 

 

 

4)一维数组的插入排序二分法

int a[10];

int l,r,mid;

 

for(i = 0;i < 10;i++)

{

scanf("%d",&a[i]);

 

//排序

//找插入位置

//二分法/二分查找法

l = 0;

r = i;

while(l <= r)

{

mid = (l+r)/2;

if(a[mid] == a[i])

{

break;

}

else if(a[mid] < a[i])

{

l = mid+1;

}

else

{

r = mid-1;

}

}

 

//插入操作

//把插入位置及后面的元素,每一个都往后移

x = a[i];

//mid,...i-1

for(j = i-1;j >= mid;j--)

{

a[j+1] = a[j];

}

a[mid] = x;

 

}

 

7 5 6 3 2 4

 

5   6         7

mid     i-1  i

 

 

回顾:

一维数组

定义:

 

数据元素的类型 数组名[数组元素个数];

 

 

int a[4];

 

数组a中有4个元素 a[0] a[1] a[2] a[3] ,每个元素int

 

typeof(a) =>int[4]

 

 

=>假如我们要定义3个像a这种类型的对象

 

对象 =》数组

 

 

typeof(a) b[3];

 

=>b数组名,它里面有3个元素,分别是b[0],b[1],b[2]

并且这三个元素都是typeof(a)

 

typeof(a) =>int[4]

 

int[4] b[3];

 

b[0]   _ _ _ _

b[1]   _ _ _ _

b[2]   _ _ _ _

 

 

每个元素代表着一个一维数组,且每个里面有4int

 

int[4] b[3]; //关键字不能与[]在一块

 

int b[3][4];

 

二维数组实际上是一个一维数组,只不过该一维数组中的元素又是一个一维数组

 

1.二维数组

1.1二维数组的实质

是一个一维数组

 

1.2 二维数组的定义

类型说明符 数组名[常量表达式(行大小)][常量表达式(列大小)];

 

1.3 二维数组在内存中的存放

int a[3][4];

 

sizeof(a) => 3*4*4

 

按行存放,即先存放第一行的元素,在放第二行的元素

 

1.4 二维数组的引用

 

数组名[行下标][列下标]

 

下标:从0开始

 

1.5 二维数组的初始化

(1)分行给二维数组赋初值

int b[3][4];

typeof(b) =>int[4][3]

int b[3][4] = {

{1,2,3,4},//b[0]

{2,3,4,5},//b[1]

{3,4,5,6}//b[2]

};

 

(2)将所有数据写在一个花括号内,按数组排列顺序对各元素赋初值

int b[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

 

(3)对部分元素赋初值,其余元素自动置0

int b[3][4] = {{1},{2,3},{4,5}};

 

or

 

int b[3][4] = {1,2,3,4};

 

(4)如果对全部元素赋初值,则定义数组时对第一维的长度省略,但第二维的长度不可以

 

int [][4] = {1,2,3,4,5,6,7,8};

 

 

2.字符数组

元素都是字符形式

 

字符串的结束标志 '\0'

 

char s[] = {'a','b','c','\0'};

 

%s :格式符 输出字符串

 遇到第一个\0结束

 

printf("%s\n",s);

 

 

字符串的操作函数:

strlen :求字符串的长度,

遇到第一个\0结束

strlen("gvjh") =>4

 

strcmp :字符串的比较函数

 

strcmp(s1 ,s2)

s1 > s2 return 1

s1 == s2  return 0

s < s2   return -1

 

strcat :字符串连接函数

s1 : "1234"

s2 : "asdf"

 

strcat(s1,s2);

 =>1234asdf

 

strcpy :字符串拷贝

s1 : "1234"

s2 : "asdf"

 

strcpy(s1,s2);

 =>asdf

 

练习:

1)定义一个整型二维数组,从键盘上给各个元素赋值

在把整个数组输出

 

2)求一个二维数组的最大值,最小值,及所有元素的和

 

 

3)求一个二维数组中列元素之和最大的那个列

int a[3][4]

 

(1)构造一个一维数组b[4],用来保存目标二维数组每一列的元素之和

int b[4] = {0};

 

b[0] += a[0][0]

 

for(i = 0;i < 4;i++)//列下标

{

for(j = 0;j < 3;j++)//行下标

{

b[i] += a[j][i]

}

 

}

 

int max = b[0];

int i_max ;

for(i = 0;i < 4;i++)

{

if(max < b[i])

{

max = b[i];

i_max = i;

}

}

 

 

 

 

 

4)求一个二维数组山顶元素的个数,打印出山顶元素是哪个及其它的位置

 

判断a[i][j]是否为山顶元素,实际上就是判断比上,下,左,右都大

 

1 2 3 5

4 5 2 4

1 2 3 5

2 5 6 3

 

:不存在 ,存在 (比它大)

:不存在 ,存在 (比它大)

:不存在 ,存在 (比它大)

:不存在 ,存在 (比它大)

 

if(上::不存在 ,存在 (比它大)&&下 :不存在 ,存在 (比它大) && 左 :不存在 ,存在 (比它大)

&& 右 :不存在 ,存在 (比它大))

{

 

}

 

=

int a[4][4]

 

if((i==0 || a[i][j] > a[i-1][j]) &&

(i == 3 || 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("a[%d][%d] = %d\n",i,j,a[i][j]);

}

 

 

 

 

 

 

//第四题,求一个二维数组中山顶元素的个数,也就是比四周的元素都大

//未知行列

 

 

//第三题,求一个二维数组中列元素之和的最大那个列

/* int a[3][3];

int i = 0, j;

for(i = 0; i < 3; i++)

for(j = 0; j < 3; j++)

{

scanf("%d", &a[i][j]);

}

int b[3] = {0};

for(j = 0; j < 3; j++)

{

for(i = 0; i < 3; i++)

{

b[j] += a[i][j];

}

}

if(b[0] >= b[1] && b[0] >= b[2])

{

printf("1\n");

}

if(b[1] >= b[2] && b[1] >= b[0] )

{

printf("2\n");

}

else

{

printf("3\n");

} */

 

 

//第一题,定义一个整型的二维数组,从键盘上给各个元素赋值,再把整个数组输出

/*int a[3][3];

int i = 0, j;

for(i = 0; i < 3; i++)

for(j = 0; j < 3; j++)

{

scanf("%d", &a[i][j]);

}

for(i = 0; i < 3; i++)

for(j = 0; j < 3; j++)

{

printf("%d\n", a[i][j]);

}*/

 

//第二题,求一个二维数组的max, min, sum

  /* int a[2][2];

int i, j, sum = 0, min = 0, max = 0;

for(i = 0; i < 2; i++)

for(j = 0; j < 2; j++)

{

scanf("%d", &a[i][j]);

}

for(i = 0; i < 2; i++)

for(j = 0; j < 2; j++)

{

sum += a[i][j];

if(a[i][j] <= min)

{

min = a[i][j];

}

if(a[i][j] >= max)

{

max = a[i][j];

}

}

printf("%d,%d, %d\n", min, max, sum); */

 

 

 

 

 

 

 

作业:

1打印杨辉三角前10

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

 

 

 

2高数巨占座位

a[6][6];

n = 3

 

0 0 0 1 1 0

0 0 0 1 1 0

0 1 0 1 0 1

0 0 0 0 0 0

0 1 1 0 1 0

0 1 0 1 0 0

 

求有多少种方式

 

3.求一个一维数组最大子数组之和

子数组:在一个数组中下标连续的n个元素(n>0),称为原数组的子数组

 

2 -1 3

 

2  =>2

2 -1 => 1

2 -1 3  =>4

-1 =>-1

-1 3  =>2

3  =>3

 

4.数组部分和

int a[N];

 

K

 

能不能从数组a中,任意选M个元素(M > 0,M <= N,使得这M个元素和为K,元素不要求连续

 

a:2 5 6 3 1 -1 -2 2

 

 

M = 3 (自己输)

K = 6 (自己输)

 

 

 

 

自己做的

第一题

#include<stdio.h>

 

int main()

{

printf("汉字测试:\t You know the test begin:\n");

//

 

//杨辉三角前10

// 1

// 11

// 121

// 1331

// 14641

int s[10][10] = {{1},{1,1}};

int i, j;

 

for(i = 0; i < 10; i++)

for(j = 0; j < 10; j++)

{

            if(j == 0 || i == j)

            {

                s[i][j] = 1;

            }

            else

            {

                 s[i][j] = s[i-1][j] + s[i-1][j-1];

            }

            printf("%d\t", s[i][j]);

 

            if(i == j)

            {

                printf("\n");

                break;

            }

        }

return 0;

}

 

     /*   if(j == 0)//就是首直接设置

        {

            s[i][j] = 1;

            printf("%d\t", s[i][j]);

        }

        if(j == i)//就是尾直接设置

        {

            s[i][j] = 1;

            printf("%d\n", s[i][j]);

            break;

        }

        //其余位置

        s[i][j] = s[i-1][j] + s[i-1][j-1];

        printf("%d\t", s[i][j]);*/

 

第二题

#include<stdio.h>

 

int main()

{

// 1.高数巨占座位

// a[6][6];

// n = 3

// 0 0 1

// 1 0 0

// 1 0 1

 

// 0 0 0 1 1 0

// 0 0 0 1 1 0

// 0 1 0 1 0 1

// 0 0 0 0 0 0

// 0 1 1 0 1 0

// 0 1 0 1 0 0

 

// 求有多少种方式

printf("汉字测试:\t You know the test begin:\n");

 

int i, j, o, p, n, resolution = 0, flag = 0;//op为输入的行列

scanf("%d%d%d", &o, &p, &n);

int arg[o][p];

for(i = 0; i < o; i++)

for(j = 0; j < p; j++)

{

scanf("%d", &arg[i][j]);

}

 

for(i = 0; i < o; i++)

{

for(j = 0; j < p; j++)

{

if(arg[i][j] == 0)//还需要考虑一种情况,就是碰到1重置

{

flag++;

if(flag == n)

{

resolution++;

//这里更换了位置

}

}

else

{

flag = 0;//调换到这里来,才可以处理碰到1重置

}

}

flag = 0;

}

 

printf("这里有这么多种方案:%d\n", resolution);

 

 

 

 

return 0;

}

 

第三题

#include<stdio.h>

#define N 3

int main()

{

// 2.求一个一维数组最大子数组之和

// 子数组:在一个数组中下标连续的n个元素(n>0),称为原数组的子数组

 

// 2 -1 3

 

// 2  =>2

// 2 -1 => 1

// 2 -1 3  =>4

// -1 =>-1

// -1 3  =>2

// 3  =>3

int arg[N], i, j , max = 0, sum;

for(i = 0; i < N; i++)

{

scanf("%d", &arg[i]);

}

 

sum = arg[0];

 

for(i = 0; i < N; i++)

{

    max = 0;

max += arg[i];

for(j = i + 1; j < N; j++)

{

max += arg[j];

if(max > sum)

{

sum = max;

}

}

}

 

printf("这个最大的数为:%d\n", sum);

return 0;

}

 

自己第一次做的

 

#include<stdio.h>

 

int main()

{

// 2.求一个一维数组最大子数组之和

// 子数组:在一个数组中下标连续的n个元素(n>0),称为原数组的子数组

 

// 2 -1 3

 

// 2  =>2

// 2 -1 => 1

// 2 -1 3  =>4

// -1 =>-1

// -1 3  =>2

// 3  =>3

 

int m, i, n, flag = 0, max = 0, j = 0;//j用来记录第二个数组的,记录max的大小

scanf("%d%d", &m, &n);//m是数组长度,nn个元素

int b[m], arg[m];//b数组用来记录连续子数组的大小

 

for(i = 0; i < m; i++)

    {

        b[i] = 0;

    }

 

 

for(i = 0; i < m; i++)//输入数组

{

scanf("%d", &arg[i]);

}

 

for(i = 0; i < m; i++) //arg[0]开始往后计数

{

max += arg[i]; //累加

flag++;

if(flag == n)       //标记n个就重置

{

printf("the flag is full\n");

flag = 0;

b[j++] = max; //连续记录

max = 0;

i -= n - 1; //倒退n-1

}

}

 

max = b[0];

for(i = 0; i < m ; i++)

{

        printf("all of the b[i] are:%d\n", b[i]);

if(b[i] >= max)

{

printf("the value of b[i] is:b[%d]\n", b[i]);

max = b[i];

}

}

 

printf("the maximum value is:%d\n", max);

 

 

 

 

 

 

return 0;

}

 

 

 

 

答案

作业:

1.高数巨占座位

a[6][6];

n = 3

 

0 0 0 1 1 0    1

0 0 0 1 1 0    1

0 1 0 1 0 1   

0 0 0 0 0 0    4

0 1 1 0 1 0    

0 1 0 1 0 0   

 

int count = 0;//表示一行连续 0个数

int s = 0;//总的占座位的方式

 

for(i = 0;i < 6;i++)

{

count = 0;

for(j = 0;j < 6;j++)

{

if(a[i][j] == 0)

{

count++;//连续为0的个数加1

if(count >= 3)

{

s++;

}

}

else

{

count = 0;

}

}

}

printf("s = %d\n",s);

求有多少种方式

 

2.求一个一维数组最大子数组之和

子数组:在一个数组中下标连续的n个元素(n>0),称为原数组的子数组

 

2 -1 3

 

2  =>2

2 -1 => 1

2 -1 3  =>4

-1 =>-1

-1 3  =>2

3  =>3

 

算法1

所有的子数组

a1  所有开头的子数组

a1

a1+a2

a1+a2+a3

 

j = 0;

sum = a[0];

j = 1;

sum = a[0] +a[1]

j = 2;

sum = a[0]+a[1]+a[2]

 

max = a[0];

sum = a[0];

for(j = 1;j < N;j++)

{

sum += a[j];

if(sum > max)

{

max = sum;

}

 

}

 

=>

max = a[0];

for(i = 0;i < N;i++)//i开头的子数组

{

sum = a[i];

 

for(j = i+1;j < N;j++)

{

sum += a[j];

if(sum > max)

{

max = sum;

}

 

}

}

 

 

算法2

+ - + - - + +

sum = 0;

max = a[0];

 

for(i = 0;i < N;i++)

{

sum += a[i];

if(max < sum)

{

max = sum;

}

 

if(sum < 0)

sum = 0;

}

 

 

3.数组部分和

int a[N];

 

K

 

能不能从数组a中,任意选M个元素(M > 0,M <= N,使得这M个元素和为K,元素不要求连续

 

a:2 5 6 3 1 -1 -2 2

 

 

M = 3 (自己输)

K = 6 (自己输)

 

2 5 6 3 1 -1 -2 2

 

对于数组中的任意一个元素a[i] ,只有两种情况

选中 1

不选  0

 

0 0 0 0 0 0 0 0 0   不选任意一个数组元素

1 0 0 0 0 0 0 0 1    选中a[0]

2 0 0 0 0 0 0 1 0    选中a[1]

3 0 0 0 0 0 0 1 1    选中a[0] a[1]

 

0 0 0 0 0 1 1 1

.....

2^n-1 1 1 1 1 1 1 1 1

 

(2^n -1)

 

0 ~2^n-1

 

x [0~2^n-1]

 

for(x = 0; x <=(1<<n)-1;x++)

{

for(j = 0;j < n;j++)

{

if(x & (1 << j))

{

//x的第jbit1

sum += a[j];

}

}

 

if(sum == k)

{

 

}

}

 

Copyright © 2024 不叫柒桓叶
Powered by .NET 9.0 on Kubernetes