• 【C语言】逆置算法


    目录

    逆置字符串

    循环版本 

    递归版本 

    旋转数组

    暴力求解法 

    反转法

    结语 


      在力扣或者牛客网这些OJ刷题平台经常能够看到一些题目,要求你将字符串逆置或者旋转字符串、亦或者旋转数组。那今天就跟大家讲解一下逆置算法。首先我们来学习一下逆置字符串。

    逆置字符串

    思路:

    逆置字符串,循环的方式实现非常简单

      1. 给两个指针,left放在字符串左侧,right放在最后一个有效字符位置

      2. 交换两个指针位置上的字符

      3. left指针往后走,right指针往前走,只要两个指针没有相遇,继续2,两个指针相遇后,逆置结束

    循环版本 

    代码示例:

    1. #include
    2. #include
    3. void reverse_string(char* arr)
    4. {
    5. char *left = arr;
    6. char *right = arr+strlen(arr)-1;
    7. while(left
    8. {
    9. char tmp = *left;
    10. *left = *right;
    11. *right = tmp;
    12. left++;
    13. right--;
    14. }
    15. }
    16. int main()
    17. {
    18. char arr[] = "joyy";
    19. reverse(arr);
    20. printf("%s\n", arr);
    21. return 0;
    22. }
    1. #include
    2. #include
    3. void reverse_string(char* arr)
    4. {
    5. int len = strlen(arr);
    6. int i = 0;
    7. for (i = 0; i < len / 2; i++)
    8. {
    9. char temp = *(arr + i);
    10. *(arr + i) = *(arr + len - 1 - i);
    11. *(arr + len - 1 - i) = temp;
    12. }
    13. }
    14. int main()
    15. {
    16. char arr[] = "joyy";
    17. reverse_string(arr);
    18. printf("%s\n", arr);
    19. return 0;
    20. }

    递归版本 

    递归方式:

    对于字符串“abcdefg”,递归实现的大概原理:

      1. 交换a和g,

      2. 以递归的方式逆置源字符串的剩余部分,剩余部分可以看成一个有效的字符串,再以类似的方式逆置

    代码示例: 

    1. #include
    2. #include
    3. void reverse_string(char* arr)
    4. {
    5. int len = strlen(arr);
    6. char tmp = *arr;
    7. *arr = *(arr+len-1);
    8. *(arr+len-1) = '\0';
    9. if(strlen(arr+1)>=2) //判断条件改为strlen(arr+1)>0也行
    10. reverse_string(arr+1);
    11. *(arr+len-1) = tmp;
    12. }
    13. int main()
    14. {
    15. char arr[] = "joyy";
    16. reverse_string(arr);
    17. printf("%s\n", arr);
    18. return 0;
    19. }

      注意:上面循环的两个版本思路差不多,使用while循环的实现方式是通过指针加加减减来实现交换,而for循环的实现方式是通过下标的方式来堆成交换。 然后递归版本最需要注意的点就是:将*(str+len-1)赋给*arr后,一定要将*(str+len-1)改为'\0'以减小字符串的长度,否则无法实现递归。

    旋转数组

    示例:给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
    示例:
    输入: [1,2,3,4,5,6,7] 和 k = 3
    输出: [5,6,7,1,2,3,4]
    解释:
    向右旋转 1 步: [7,1,2,3,4,5,6]
    向右旋转 2 步: [6,7,1,2,3,4,5]
    向右旋转 3 步: [5,6,7,1,2,3,4]

    暴力求解法 

    分析:

    代码示例:

    1. #include
    2. void rotate(int* nums, int numsSize, int k)
    3. {
    4. k %= numsSize;
    5. for (int i = 0; i < k; i++)
    6. {
    7. int temp = nums[numsSize - 1];
    8. for (int k = numsSize - 2; k >= 0; k--)
    9. {
    10. nums[k + 1] = nums[k];
    11. }
    12. nums[0] = temp;
    13. }
    14. }
    15. int main()
    16. {
    17. int arr[] = { 1,2,3,4,5,6,7 };
    18. rotate(arr, 7, 10);
    19. for (int i = 0; i < 7; i++)
    20. {
    21. printf("%d ", arr[i]);
    22. }
    23. return 0;
    24. }

      这种方法还是比较容易想到的方法,但是它不是最优的方法。接下来,博主给大家介绍一种更加优的方法。 

    反转法

    分析:

      反转法主要涉及了三次逆置:第一次是前n-k个元素逆置,第二次是后k个元素逆置,第三次是整个数组逆置。所以反转法需要借助上面已经介绍到了的逆置算法。

    代码示例:

    1. void rotate(int* nums, int numsSize, int k)
    2. {
    3. k %= numsSize;
    4. //前n-k个元素逆置
    5. reverse(nums, 0, numsSize - k - 1);
    6. //后k个元素逆置
    7. reverse(nums, numsSize - k, numsSize - 1);
    8. //整个数组逆置
    9. reverse(nums, 0, numsSize - 1);
    10. }
    11. int main()
    12. {
    13. int arr[] = { 1,2,3,4,5,6,7 };
    14. rotate(arr, 7, 3);
    15. for (int i = 0; i < 7; i++)
    16. {
    17. printf("%d ", arr[i]);
    18. }
    19. return 0;
    20. }

      以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以给个三连支持一下!谢谢大家啦!

    结语 

      每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根。

  • 相关阅读:
    MRI多任务技术及应用
    P2763 试题库问题
    Find My音箱|苹果Find My技术与音箱结合,智能防丢,全球定位
    elasticsearch,为什么prefix性能消耗很大
    Java之反射
    web基础与HTTP协议
    hive表中导入数据 多种方法详细说明
    LoadRunner负载机和IP欺骗
    ref和reactive
    《深度探索C++对象模型》阅读笔记 第二章 构造函数语意学
  • 原文地址:https://blog.csdn.net/m0_63639164/article/details/126025192