引用:
int a,b,c,d,......
int sum
=>
定义一类或一组变量
数组
1.数组是什么?
数组是一组具有相同类型的数据(变量)的集合
C语言中数组:
一维数组
二维数组
三维数组
...
其实,C语言中只有一维数组
2,一维数组
2.1 定义格式
类型说明符 数组名[整型表达式] {={初始化列表}};
{}: 可要可不要
"类型说明符":指定数组元素的类型,任意C语言合法的类型都可以
“数组名”:对象的名字,命名要符合C语言标识符的规定
“整型表达式” :指定数组中元素的个数,一般为常量表达式
eg:
#define N 3
int a[10];//定义了一个数组,数组名a,里面有10个int型元素
typeof(a) =>一个具有10个int元素的数组类型 int[10]
char b[10];
typeof(b) => 一个具有10个char元素的数组类型 char[10]
int c;//在程序运行的时候,为c分配4个字节的空间
在程序运行的时候,为a分配多大的空间?
10个int =》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);
(2)Fibonacci(斐波那契数列前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 R,KeyType K)
{ //在有序表R[1..n]中进行二分查找,成功时返回结点的位置,失败时返回零
int low=1,high=n,mid; //置当前查找区间上、下界的初值
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=2;i<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] _ _ _ _
每个元素代表着一个一维数组,且每个里面有4个int
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是数组长度,n是n个元素
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的第jbit为1
sum += a[j];
}
}
if(sum == k)
{
}
}