1.下面哪个代码是错误的( )
int main()
{
int* p = NULL;
int arr[10] = { 0 };
return 0;
}
A: p = arr
B: int(*ptr)[10] = &arr
C: p = &arr[0]
D: p = &arr
解释:D - 数组的地址要放数组指针,p是整形指针,所以error
2.下列代码输出什么呢?
int main()
{
char str1[] = "hello bit";
char str2[] = "hello bit";
char str3 = "hello bit";
char str4 = "hello bit";
if (str1 == str2)
printf("str1 and str2 are same\n"); 一
else
printf("str1 and str2 are not same\n"); 二
if (str3 == str4)
printf("str3 and str4 are same\n"); 三
else
printf("str3 and str4 are not same\n"); 四
return 0;
}
result:二和三
解释:一和二是数组名,数组名是表示首元素的地址,并且一和二会开辟两个不同的空间,那么它们的地址自然就不相同啦~; 三和四是常量字符串,常量字符串相同不会存两份的,所以它们是相同的(现在VS2019打常量字符串都是必须加const的哦!)
3.杨氏矩阵
题目内容:
有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的(没说是等差递增哦)
请编写程序再这样的矩阵种查找某个数字是否存在
要求 : 时间复杂度小于O(N); O(N) = 假设数组有N个元素,那么查找的次数最坏的情况下是N次
思路:
矩阵例子:
1 2 3
4 5 6
7 8 9
会发现每行的最后一个元素是最大的,那么要找的数字可以直接和最后一个元素对比,如果比它大就跳过,比它小就再这行里用列找即可。或者用一列里最大的来比,小的就在这一列里用行找。
代码实现:
int find_num(int arr[3][3], int r, int c, int k)
{
int x = 0;
int y = c - 1;
while (x < r && y >= 0)
{
if (arr[x][y] < k)
{
x++;
}
else if (arr[x][y] > k)
{
y--;
}
else
{
printf("%d %d\n", x, y);
return 1;//找到了
}
}
return 0;//找不到
}
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int k = 7;
//如果找不到返回1,找不到返回0
int ret = find_num(arr, 3, 3, k);
if (ret == 1)
{
printf("找到了\n");
}
else
{
printf("找不到了\n");
}
//查找一个数字
//不满足时间复杂度小于O(N)
//int i = 0;
//int j = 0;
//for (i = 0;i < 3;i++)
//{
// for (j = 0;j < 3;j++)
// {
// if (arr[i][j] == 7)
// {
// //....
// }
// }
//}
return 0;
}
可以find_num不是用来找的嘛,怎么就打印了?那么该怎么办呢 ?
那我们来调用下为数不多的脑细胞吧 - 函数传值不可以修改变量,传址可以修改变量,既然有思路了试试实现它
int find_num(int arr[3][3], int* px, int* py, int k)
{
int x = 0;
int y = *py - 1;
while (x < *px && y >= 0)
{
if (arr[x][y] < k)
{
x++;
}
else if (arr[x][y] > k)
{
y--;
}
else
{
*px = x;
*py = y; //坐标带回去力!
return 1;
}
}
return 0;
}
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int k = 7;
int x = 3;//行
int y = 3;//列
int ret = find_num(arr, &x, &y, k);
if (ret == 1)
{
printf("找到了\n");
printf("下标是:%d %d\n", x, y);
}
else
{
printf("找不到了\n");
}
return 0;
}
&x和&y有两个作用:1.传入参数 2.带回值 (完美实现)
4.字符串左旋:
实现一个函数,可以左旋字符串中的k个字符
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
思路:
要实现左旋,要先拿个地址存放字符,把要左旋的字符放入这个地址里然后把后面的元素往前拿,就可以实现一个左旋,如果要实现两个及以上加个循环就可以了
代码实现:
void string_left_rotate(char* str, int k)
{
int i = 0;
int n = strlen(str);
for (i = 0;i < k;i++)
{
//每次左旋转一个字符
//1.把第一个字符拿出来
char tmp = *str;
//2.后面的n-1字符往前挪动
int j = 0;
for (j = 0;j < n - 1;j++)
{
*(str + j) = *(str + j + 1);
}
//3.tmp放在最后
*(str + n - 1) = tmp;
}
}
int main()
{
char arr[10] = "ABCDEF";
int k = 2;
string_left_rotate(arr,k);
printf("%s\n", arr);
return 0;
}
so easy啦~
还有其他解法嘛?
思路:
可以把要旋转的字符当成一部分,把不要旋转的当一部分,把它们分别逆序一次,再整体逆序一次,即可完成
例子:
A B C D E F -> B A F E D C -> C D E F A B
代码实现:
#include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char* left, char* right)
{
assert(left);
assert(right); //养成断言的好习惯哦~
while (left < right)
{
char tmp = *left; //1.把第一个元素的指针放到tmp里
*left = *right; //2.最后个元素放第一个元素的地址里
*right = tmp; //3.第一个元素放最后个元素的地址里
left++;
right--;
}
}
void string_left_rotate(char* str, int k)
{
assert(str);
int n = strlen(str);
reverse(str, str + k - 1); //左
reverse(str + k, str + n - 1); //右
reverse(str, str + n - 1); //整体
}
int main()
{
char arr[10] = "ABCDEF";
int k = 2;
string_left_rotate(arr,k);
printf("%s\n", arr);
return 0;
}
5.字符串旋转结束
写一个函数,判断一个字符串是否位另外一个字符串旋转之后的字符串
例如:
给定s1 = AABCD和s2 = BCDAA,返回1
给定s1 = abcd和s2 = ABCD,放回0
代码实现:
int is_string_rotate(char* str1, char* str2)
{
int i = 0;
int n = strlen(str1);//5
for (i = 0;i < n;i++)
{
char tmp = *str1;
int j = 0;
for (j = 0;j < n - 1;j++)
{
*(str1 + j) = *(str1 + j + 1);
}
*(str1 + n - 1) = tmp;
if (strcmp(str1, str2) == 0)
{
return 1;
}
}
return 0;
}
int main()
{
char arr1[] = "AABCD";
char arr2[] = "BCDAA";
int ret = is_string_rotate(arr1, arr2);
if (ret == 1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
}
那么还有其他实现方法吗?
思路:再造一个字符串AABCD AABCD ,会发现它包含了所有字符旋转的可能性,那么把BCDAA放进去找,如果找到了它就是旋转的结果
我们先来认识一个新的函数,strcat()和strncat();
例子:
int main()
{
char arr1[20] = "hello ";
char arr2[20] = "hello ";
strcat(arr1,"bit"); //引用头文件<string.h>,后面加bit
strncat(arr2, arr2, 5); //后面加arr,5个元素
printf("%s\n", arr1); //hello bit
printf("%s\n", arr2); //hello hello
return 0;
}
代码实现:
int is_string_rotate(char* str1, char* str2)
{
//长度不相等,肯定不是旋转得来的
if (strlen(str1) != strlen(str2))
{
return 0;
}
//1.str1字符串的后边追加一个str1
//AABCDAABCD
int len = strlen(str1);
strncat(str1,str1,len); //字符串追加
//2.判断str2是否为str1的子串
char* ret = strstr(str1,str2); //判断一个字符串是不是另外一个字符串的子串
//str1:AABCDAABCD
//str2: BCDAA
//找到了返回一个地址,找不到返回一个空指针
return ret != NULL;//简化结果,但是有个小的漏洞,比如BCD也是它的子串
//那么就在开头补充判断条件
//if (ret == NULL) //可以像上面那样简化
//{
// return 0;
//}
//else
//{
// return 1;
//}
}
int main()
{
char arr1[20] = "AABCD";
char arr2[] = "BCDAA";
int ret = is_string_rotate(arr1, arr2);
if (ret == 1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
}
指针总结:
指针: 数组: 指针运算:
一级指针 一维数组 解引用
二级指针 二维数组 指针+-整数
整形指针 整形数组 指针-指针
字符指针 字符数组 指针的关系运算
.. ..
数组指针 指针数组
函数指针
指针一定要学好,数据结构要用哦~!
如果喜欢我的博文可以点赞收藏关注,我将会为你带来更多优质文章!