目录
11.Here is Tulun ==>Tulun is Here
1.求斐波那契数列前40项
解题思路:将前两项初始化为1,从第三项开始进行计算。
void Fabonacio(int *arr,int len)
{
assert(arr != NULL && len > 0);
arr[0] = 1;
arr[1] = 1;
for(int i = 2;i < len;i++)
{
arr[i] = arr[i-1]+arr[i-2];
}
}
void Show(int *arr,int len)
{
for(int i = 0;i < len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[20] = {};
int len = sizeof(arr)/sizeof(arr[0]);
Fabonacio(arr,len);
Show(arr,len);
return 0;
}
递归版本:
int Job(int n)
{
int f3=0;//第三项初始化
if(n==2)
{
return 1;
}
if(n==1)
{
return 1;
}
else
{
f3=Job(n-1)+Job(n-2);//第三项==前两项的和
return f3;
}
}
int main()
{
printf("%d\n",Job(8));
return 0;
}
2.求连续子数组的最大和
void Job1(int arr[],int n)//传递数组和数组所包含元素个数
{
int i,j,max,sum,start,end;
max=arr[0];//将第一个元素付给max,相当于子序列只有一个元素时的最大值
for(i=0;i<n;i++)
{
sum=arr[i];
for(j=i+1;j<n;j++)
{
sum+=arr[j];//求连续子序列的和
if(max<sum)//判断求和与max的大小
{
max=sum;
start=i;//当数组的max发生改变时,记录开始上标==》有可能这个上下标之间的和是最大的
end=j;//记录下标
}
}
}
printf("子数列的最大和为:%d\n",max);
printf("开始下标为:%d\n",start);
printf("结束下标为:%d\n",end);
}
int main()
{
int arr[5]={10,-1,9,-100,-10};
Job1(arr,5);
return 0;
}
解题思路:累加与max进行比较,如果max发生改变,说明产生最大值(当前),记录当上时的起始和终止的下标。
int MaxNum(int *arr,int len)
{
assert(arr != NULL && len > 0);
int max = 0x80000000;
int sum = 0;
for(int i = 0; i < len;i++)
{
sum = 0;//第二趟的时候
for(int j = i;j < len;j++)//O(n^2)
{
sum += arr[j];//10 9 18 -82
if(sum > max)
{
max = sum;//10 18
}
}
}
return max;
}
int MaxNum2(int *arr,int len)
{
assert(arr != NULL && len > 0);
int max = 0x80000000;
int sum = 0;
for(int i = 0; i < len;i++)
{
//sum = 0;
if(sum <= 0)
{
sum = arr[i];//10
}
else
{
sum += arr[i];//9 18 -82
}
if(sum > max)
{
max = sum;//10 18
}
}
return max;
}
int main()
{
int arr[10] = {};
int len = sizeof(arr)/sizeof(arr[0]);
int max = MaxNum2(arr,len);
printf("%d\n",max);
return 0;
}
3.辗转相处,求最大公约数
int Fun(int m,int n)//辗转相处,求最大公约数
{
assert(m*n!=0);
int tmp=0;
if(m<n)
{
tmp=n;
n=m;
m=tmp;
}
while(m%n!=0)
{
tmp=m%n;//15 10===>5
m=n;
n=tmp;
}
return n;
}
4.判断大小端
bool IsBig()
{
int a = 0x12345678;
char *p = (char *)&a;
if(*p == 0x78)
{
return false;//小端
}
else
{
return true;//大端
}
}
联合体判断大小端
union Data
{
int a;
char b;
};
void Job(Data test)
{
if(test.b==0x78)
{
printf("小端储存\n");
}
else
{
printf("大端储存\n");
}
}
解题思路:联合体共用一块内存,同一时间只保存一个数据
5.大小端的转换
void Job(char *p,int len)
{
int n=len/2; //将数据一分为二 1234 5678
char c;
for(int i=0;i<n;i++)//相互调换
{
c=*(p+i);
*(p+i)=*(p+(len-i-1));
*(p+(len-i-1))=c;
}
}
int main()
{
char arr[]="Here is Tulun";
printf("%s\n",arr);
int len=sizeof(arr)/sizeof(arr[0]);
Job1(arr,len);
printf("%s\n",arr);
return 0;
}
解题思路:将数据一分为二1234 5678
另一个版本:
unsigned int Fun(unsigned int n)
{
return ( ((n&0xff000000) >>24) | ((n&0x00ff0000) >>8)
| ((n&0x0000ff00) <<8) | ((n&0x000000ff) <<24) );
}
int main()
{
unsigned int n=0x12345678;
Fun(n);
return 0;
}
6.int类型 指针 float 和零值如何比较
解:
(1)int类型:
int i=0;
if(i==0);if(i!=0);
直接和0比较就好。
(2)指针:
int *p=NULL;
if(NULL==p);if(NULL!=p);
为什么要这样写,因为1.怕漏写一个'=';2.NULL表示的是内存中的起始地址,即0x00000000。NULL在数值上==0;
(3)float类型:
float a=0.0;
if((a>=-EPSINON)&&(a<=EPSINON));
因为float和double是有精度限制的,不能够直接拿来和0.0进行比较。必须设置一个精度范围,而假设EPSINON是一个定义好的精度,如果一个数能够落在[0.0-EPSINON,0.0+EPSINON]这个区间之内,则说明在某个精度内与零值相等。
(4)bool类型:
bool flag=false;
if(flag);if(!flag);
bool类型本身返回的就是true或false,1或者0。所以在与“零值”判断时直接使用变量本身。
但有的编译器对true定义的不是1,所以要初始化一个0,判断0和非0即可。
一般情况下对bool类型的初始化都为false,这是因为如果不进行初始化,默认的地址是随机分配的,即非0值,所以要对bool进行初始化,并赋值为false。
7.对指针的理解
在定义指针时我们常写成int a=5;int *p;p=&a;这个东西就弄的我很茫然,有时候书上又会出现一句“int *p=5;”我根本分不清他们两者之间的区别。而在xxx的书上说的他们是一样的。但其实他们真的是不一样,定义int *p;这样写应该是为了好看,它实际应该写成int* p;这样的定义才能让人理解这是定义了一个指向int型的指针,它叫做p,这个p只能放地址,如果你写成了"int *p=5;"这个5就会被当做是地址处理。定义指针时要初始化给NULL,这是因为在编译其中NULL就表示的是内存的其实地址,也就是0x00000000.它的作用就是初始化指针变量,不让指针变量指向一个非法的地址。
8.const 和 define 区别??
解:
const修饰的是"只读的变量",其值在编译时不能被使用。所以可以理解为const==readonly。
const修饰的只读变量是在编译的时候确定其值,而define宏定义是在预编译的时候进行替换。
const修饰的只读变量有类型,而define宏定义没有,只是常数。
编译器会给const修饰的只读变量做类型校验,减少错误的可能,而define宏定义没有。
编译器不为const修饰的只读变量分配存储空间,而将它们保存在符号表中,只读变量在运行中只有一份备份;
而define宏定义在内存中有若干个备份。
const修饰的只读变量必须在定义的同时初始化,因为const修饰的是只读变量只能读,不能写。在定义之后就不能再进行修改,所以要定义的同时初始化。
9.求字符串单词个数
int Job(char *str)
{
int sum=0;//用来记录两个词之间的空格数
char *pbegin=str;
char *pend=str;
assert(str!=NULL);
while(*pend!='\0')
{
if(*pbegin==' ')//如果起始输入的是空格,则将指针移向第一个字母
{
while(*pbegin==' ')
{
pbegin++;
pend++;
}
}
if(*pend==' '&&*(pend+1)!=' '&&*(pend+1)!='\0')//记录两个词中间的空格,且只记录一次,考虑最后的'\0'。
{
sum++;
}
pend++;
}
return sum+1;
}
int main()
{
char str[]=" ghgh asdjk sjdks ss jkj ";
printf("单词个数为:%d\n",Job(str));
return 0;
}
解题思路:在字符串中,判断他们有多少个空格(两个词中必有空格),记录空格数。
10.回文字符串
//"abcba"===》回文字符串
//思路:*pbegin *pend如果他俩值得数一直相等,则他就是一个回文数
void Fun(const char *str)
{
const char *pbegin=str;
const char *pend=str;
assert(str!=NULL);
while(*pend!='\0')
{
pend++;
}
pend--;
while(pbegin<pend)//地址
{
if(*pbegin==*pend)
{
pbegin++;
pend--;
}
else
{
printf("%s不是一个回文数\n",str);
break;
}
}
printf("%s是一个回文数\n",str);
}
int main()
{
char str[]="123421";
Fun(str);
return 0;
}
解题思路:*pbegin *pend如果他俩值得数一直相等,则他就是一个回文数。
11.Here is Tulun ==>Tulun is Here
/*
一级指针存放的是变量的地址,二级指针存放的是一级指针的地址
*/
void Reverse(char *pbegin,char *pend)
{
assert(pbegin!=NULL&&pend!=NULL);
char tmp=0;
while(pbegin<pend)//地址
{
tmp=*pbegin;
*pbegin=*pend;
*pend=tmp;
pbegin++;
pend--;
}
}
char* RevreSentence(char *str)//
{
assert(str!=NULL);
char *pbegin=str;
char *pend=str;
while(*pend!='\0')
{
pend++;
}
pend--;
Reverse(pbegin,pend);
pbegin=str;
pend=str;
while(*pbegin!='\0')
{
if(*pbegin==' ')
{
pbegin++;
pend++;
}
else
if(*pend==' '||*pend=='\0')
{
Reverse(pbegin,--pend);
pbegin=++pend;
}
else
{
pend++;
}
}
return str;
}
int main()
{
char str[]="Here is Tulun";//不能写成*str="Here is Tulun";因为字符串不能修改
RevreSentence(str);
printf("%s\n",str);
return 0;
}
解题思路:整体逆置,再对每一个单词进行逆置。
12.二分法查元素
int Binarrserach(int *arr,int len,int key)
{
int low=0;
int high=len-1;
while(low<=high)
{
int mid=(low+high)/2;//int mid=(low+high)>>1;
if(arr[mid]==key)
{
return mid;
}
else
{
if(arr[mid]>key)
{
high=mid-1;
}
else
{
low=mid+1;
}
}
}
return -1;
}
int main()
{
int arr[]={1,2,3,4,5,6,7};
int len=sizeof(arr)/sizeof(arr[0]);
printf("%d\n",Binarrserach(arr,len,4));
printf("%d\n",Binarrserach(arr,len,10));
return 0;
}
递归版本:
int Job1(int *arr,int low,int high,int key)//设置指向第一个元素的下标low和最后一个元素的下标high
{
int mid=(low+high)/2;
if(arr[mid]==key)
{
printf("%d的下标为:%d\n",key,mid);
return mid;
}
else
{
if(arr[mid]>key)
{
Job1(arr,low,mid-1,key);//改变范围
}
else
{
Job1(arr,mid+1,high,key);
}
}
}
int main()
{
int arr[5]={1,2,3,4,5};
Job1(arr,0,4,4);
return 0;
}