首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

字符指针的三道例题+算法改进

  • 25-04-24 09:20
  • 2437
  • 6904
blog.csdn.net

目录

一.杨氏矩阵

1.初级

2.想把下标带回来

二.字符串左旋

算法改进

三.判断是否为字符串旋转结果

算法改进

四. 3个字符函数

1.strcat

2.strncat

3.strstr


一.杨氏矩阵

数字矩阵,每行从左到右递增,每列从上到下递增,编写程序在矩阵中查找某个数字是否存在。

要求:时间复杂度小于O(N);

1.初级

我们采用这样的算法:

  • 由于每行每列都是递增的,用矩阵左下或右上角的数与目标数比较(右上角为例)。
  • 右上角的元素,是其所在行中最大的,列中最小的。
  • 若目标数大,则删除右上角元素所在行。用新矩阵的右上角再与目标数比较。
  • 若目标数小,则删除右上角元素所在列。用新矩阵的右上角再与目标数比较。
  • 重复以上过程,直至找到,或越界

代码演示:

  1. void find_k(int arr[3][3], int r, int c, int k)
  2. {
  3. int x = 0;
  4. int y = c - 1;
  5. int flag = 0;
  6. while (x <= r - 1 && y >= 0)
  7. {
  8. if (k > arr[x][y])
  9. {
  10. x++;
  11. }
  12. else if (k < arr[x][y])
  13. {
  14. y--;
  15. }
  16. else
  17. {
  18. printf("找到了,下标是:%d %d\n", x, y);
  19. flag = 1;
  20. break;
  21. }
  22. }
  23. if (flag == 0)
  24. printf("找不到\n");
  25. }
  26. int main()
  27. {
  28. int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
  29. int k = 7;//要查找的元素
  30. find_k(arr, 3, 3, k);
  31. return 0;
  32. }

2.想把下标带回来

难道要这样吗?

  1. else
  2. {
  3. printf("找到了,下标是:%d %d\n", x, y);
  4. flag = 1;
  5. return x, y;
  6. }

错了。没有这样写的,只能返回一个值

我们需要把x,y创建在调用函数外面,再传x,y地址。

  1. int find_k(int arr[3][3], int* px, int* py, int k)
  2. {
  3. int x = 0;
  4. int y = *py - 1;
  5. while (x <= *px - 1 && y >= 0)
  6. {
  7. if (arr[x][y] < k)
  8. {
  9. x++;
  10. }
  11. else if (arr[x][y] > k)
  12. {
  13. y--;
  14. }
  15. else
  16. {
  17. *px = x;
  18. *py = y;
  19. return 1;
  20. }
  21. }
  22. return 0;
  23. }
  24. int main()
  25. {
  26. int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
  27. int k = 17;//查找的值
  28. int x = 3;
  29. int y = 3;
  30. int ret = find_k(arr, &x, &y, k);
  31. if (ret == 0)
  32. printf("找不到\n");
  33. else
  34. printf("找到了,下标是:%d %d", x, y);
  35. return 0;
  36. }

二.字符串左旋

实现一个函数,可以左旋字符串中的k个字符。

例如:ABCD左旋一个字符得到BCDA          ABCD左旋两个字符得到CDAB

思路是这样:

左旋一个字符:

  1. 把第一个字符放进 tmp 中。
  2. 将后面的字符向前挪。
  3. 将 tmp 中的第一个字符放到最后面

左旋 k 个字符:重复 k 次。

代码演示:

  1. void left_move(char arr[], int k)
  2. {
  3. int i = 0;
  4. int len = strlen(arr);
  5. k %= len;
  6. for (i = 0; i < k; i++)
  7. {
  8. //旋转1个字符
  9. //1
  10. char tmp = arr[0];
  11. //2
  12. int j = 0;
  13. for (j = 0; j < len - 1; j++)
  14. {
  15. arr[j] = arr[j + 1];
  16. }
  17. //3
  18. arr[len - 1] = tmp;
  19. }
  20. }
  21. int main()
  22. {
  23. char arr[] = "abcdef";
  24. int k = 8;
  25. left_move(arr, k);
  26. printf("%s\n", arr);
  27. return 0;
  28. }

算法改进

当字符串比较长时,上面那种一个一个交换的方法效率低下。

我们尝试这样的思路:逆序字符串。逆序左边,逆序右边,整体逆序。

例如:

  1. #include
  2. void reverse(char* left, char* right)
  3. {
  4. assert(left);//断言指针的有效性
  5. assert(right);
  6. while (left < right)
  7. {
  8. char tmp = *left;
  9. *left = *right;
  10. *right = tmp;
  11. left++;
  12. right--;
  13. }
  14. }
  15. void left_move(char arr[], int k)
  16. {
  17. int len = strlen(arr);
  18. k %= len;
  19. //逆序左
  20. reverse(arr, arr + k - 1);
  21. //逆序右
  22. reverse(arr + k, arr + len - 1);
  23. //逆序整体
  24. reverse(arr, arr + len - 1);
  25. }
  26. int main()
  27. {
  28. char arr[] = "abcdef";
  29. int k = 8;
  30. left_move(arr, k);
  31. printf("%s\n", arr);
  32. return 0;
  33. }

三.判断是否为字符串旋转结果

写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。

例如:给定s1 =AABCD和s2 = BCDAA,返回1              给定s1=abcd和s2=ACBD,返回0

思路:每左旋一次,都进行判断。

代码演示:

  1. #include
  2. void left_move(char arr[], int k)
  3. {
  4. int len = strlen(arr);
  5. k %= len;
  6. //逆序左
  7. reverse(arr, arr + k - 1);
  8. //逆序右
  9. reverse(arr + k, arr + len - 1);
  10. //逆序整体
  11. reverse(arr, arr + len - 1);
  12. }
  13. int is_left_move(char arr1[], char arr2[])
  14. {
  15. int len1 = strlen(arr1);
  16. int len2 = strlen(arr2);
  17. if (len1 != len2)
  18. return 0;
  19. int i = 0;
  20. for (i = 0; i < len1; i++)
  21. {
  22. left_move(arr1, 1);//每次旋转1个
  23. if (strcmp(arr1, arr2) == 0)//比较
  24. {
  25. return 1;
  26. }
  27. }
  28. //从来没有 return 1; 那就不可能 YES
  29. return 0;
  30. }
  31. int main()
  32. {
  33. char arr1[] = "AABCD";
  34. char arr2[] = "ABCDA";
  35. int ret = is_left_move(arr1, arr2);
  36. if (ret == 1)
  37. {
  38. printf("YES\n");
  39. }
  40. else
  41. {
  42. printf("NO\n");
  43. }
  44. return 0;
  45. }

这种方法其实也不够简练

算法改进

各位读者先阅读 四.

上面的方法其实把 arr1 旋转后所有的可能情况都列出来了,再进行比较。

有没有办法让它直接得到所有旋转后的可能性? 有的兄弟,有的!

比如:AABCDAABCD(自己重复两遍)

发现:AABCDAABCD 里包含了 AABCD 所有旋转后的可能性。

只需要给 arr1 追加 arr1 后,去看 arr2 是不是追加后的子串。如果是,那就是 arr1 旋转得来的。

前提:如果长度不一样,要提前 Pass

注意:给 arr1 追加时,要有空间,最好 char arr1[20],给大一点。要不然程序崩了

代码演示:

  1. #include
  2. int is_left_move(char arr1[], char arr2[])
  3. {
  4. int len1 = strlen(arr1);
  5. int len2 = strlen(arr2);
  6. if (len1 != len2)
  7. return 0;
  8. strncat(arr1, arr1, len1);
  9. if (strstr(arr1, arr2) != NULL)
  10. return 1;
  11. else
  12. return 0;
  13. }
  14. int main()
  15. {
  16. char arr1[20] = "AABCD";
  17. char arr2[] = "ABCDA";
  18. int ret = is_left_move(arr1, arr2);
  19. if (ret == 1)
  20. {
  21. printf("YES\n");
  22. }
  23. else
  24. {
  25. printf("NO\n");
  26. }
  27. return 0;
  28. }

这样写,我们把大量代码依赖于库函数实现

四. 3个字符函数

1.strcat

头文件:#include

  1. #include
  2. int main()
  3. {
  4. char arr[20] = "hello ";//想在后面追加 world
  5. strcat(arr, "world");
  6. printf("%s\n", arr);
  7. return 0;
  8. }

2.strncat

头文件:#include

在 hello 后追加几个,由我们控制。用 strcat 的另一个版本:strncat

  1. #include
  2. int main()
  3. {
  4. char arr[20] = "hello ";
  5. strncat(arr, "world", 3); // 5
  6. printf("%s\n", arr);
  7. return 0;
  8. }

     

3.strstr

头文件:#include

strstr 是在arr1字符串中查找arr2是否存在

  • 如果存在则返回 arr2 在 arr1 中首次出现的地址(位置)
  • 如果不存在返回 NULL
  1. #include
  2. int main()
  3. {
  4. char arr1[] = "abcdefabcdef";
  5. char arr2[] = "def";
  6. char* ret = strstr(arr1, arr2);
  7. if (ret == NULL)
  8. {
  9. printf("不存在\n");
  10. }
  11. else
  12. {
  13. printf("%s\n", ret);
  14. }
  15. return 0;
  16. }

本篇的分享就到这里了,感谢观看,如果对你有帮助,别忘了点赞+收藏+关注。

小编会以自己学习过程中遇到的问题为素材,持续为您推送文章。

注:本文转载自blog.csdn.net的祁同伟.的文章"https://blog.csdn.net/HDSTQTW/article/details/146425988"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

113
数据结构与算法
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top