轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组 (二)

简介: 这是一个关于字符串处理的问题,要求将一句话中的单词顺序倒置,但保持单词内部的字符顺序不变。例如,"I like beijing." 变为 "beijing. like I"。解决方法可以分为三个步骤:分块、内部逆序和整体逆序。代码示例使用C语言实现,通过指针和while循环操作字符串数组。最终总结提到,无论先逆置哪个部分,只要确保所有部分都逆置过,结果都是相同的。

轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组(一)+   https://developer.aliyun.com/article/1518463?spm=a2c6h.13148508.setting.14.73ba4f0eD6sgs2


三、拓展:倒置字符串


这道题是上面三步转换法非常合适的一个变式。


1. 题干


牛客网链接  


https://www.nowcoder.com/questionTerminal/8869d99cf1264e60a6d9eff4295e5bab


将一句话的单词进行倒置,标点不倒置。

比如 "I like beijing.",经过处理后变为:"beijing. like I"

(字符串长度不超过100)



2. 思路


这也是“整体逆序,内部有序”的典例:我们将字符串内容按单词分块,单词在整个句子中的顺序发生变化,但单词还是单词,它内部的字母顺序并没有发生变化。

当我们明白这一点,接下来的事情也许会好办许多。



3. 代码


这里我们采用指针+while循环的方式来对字符串数组进行操作。这里是单纯的倒置,不存在向左或向右轮转的方向问题,因此方向这里就不用考虑了。

此外还有一些细节方面需要注意,如scanf读不了空格,当字符串中需要空格的时候,最好用gets()函数读取


//将逆置操作封装成函数
void reverse(char* left, char* right)
{
    //加了两句断言
    assert(left);
    assert(right);
 
    while (left < right)
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
}
 
int main()
{
    char arr[101] = { 0 };
    //注意要用gets()函数,因为它可以读入空格
    gets(arr);
 
    //用指针来操作数组
    char* cur = arr;
 
    //逆序每个单词
    while (*cur)
    {
        char* start = cur;
        char* end = cur;
        while (*end != ' ' && *end != '\0')
        {
            end++;
        }
        reverse(start, end - 1);
        if (*end != '\0')
            cur = end + 1;
        else
            cur = end;
    }
 
    //逆序整个字符串
    int len = strlen(arr);
    reverse(arr, arr + len - 1);
 
    printf("%s\n", arr);
 
    return 0;
}






四、总结


  1. 三步逆置:将数组分块,块内元素先分别逆置,最后再整体逆置。若无轮转顺序要求,则不需要考虑先逆置数组中的哪一块内的元素。
  2. 本文详细介绍了三步逆置法在倒置字符串和整型数组中的应用,以及两种代码实现。在倒置字符串时我们不需要考虑轮转顺序,只要达到逆置的结果即可,该代码是用指针+区间划分的思想实现的,我们用了while循环来控制。
  3. 在轮转数组的引例中,题目要求的向右轮转,我们就先将右边的k个元素逆置,再将剩下的左边(n-k)个元素逆置,最后整体逆置。虽然本文似乎有强调轮转方向的差别,但其实在数组整体逆置之前,先逆置内部哪部分是并不影响结果的,只要保证每个部分的内部都逆置过了即可。先逆置左边的(n-k)个,再逆置右边的k个,最后再整体逆置,达到的效果是一样的。强调方向仅仅是便于一些同学理解。






相关文章
|
6月前
|
设计模式 算法 Java
【数据结构和算法】寻找数组的中心下标
给你一个整数数组nums,请计算数组的中心下标。 数组中心下标是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端,那么左侧数之和视为0,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。 如果数组有多个中心下标,应该返回最靠近左边的那一个。如果数组不存在中心下标,返回-1。
97 0
【数据结构刷题】消失的数字和轮转数组(上)
【数据结构刷题】消失的数字和轮转数组(上)
|
编译器 C语言
【数据结构刷题】消失的数字和轮转数组(下)
【数据结构刷题】消失的数字和轮转数组(下)
|
6月前
|
存储 算法
轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组(一)
这篇内容讲述了数组向右轮转k个位置的问题,主要分为两种解决思路。第一种是“轮转k次法”,直接在原数组上操作,每次循环k次,将数组末尾元素移到开头,时间复杂度为O(N*K),效率较低。第二种是“额外数组法”,使用额外数组存储部分元素,然后移动原数组元素,最后归还额外数组元素,时间复杂度和空间复杂度均为O(N)。文章还介绍了更高效的“三步转换法”,通过三次逆序操作实现数组轮转,分别是逆置后k个元素、逆置前n-k个元素以及整体逆置,这种方法时间复杂度为O(N)且空间复杂度为O(1)。
74 1
|
6月前
|
存储 Python
处理随机元素来创建数列是一个涉及随机数生成和数列构造的过程
处理随机元素来创建数列是一个涉及随机数生成和数列构造的过程
57 0
|
JSON C# 数据格式
数组比较的几种方式
1、string.Equals() ```csharp string[] strList1= new string[3] {"1", "2", "3"}; string[] strList2= new string[3] {"4", "5", "6"}; if (!string.Equals(strList1, strList2)) { // 比较数组的不同之处 } // 涉及到修改日志输出等数组可以直接json序列化然后用上述方法比较即可,如下 if (!string.Equals(JsonConvert.SerializeObject(list1), JsonConvert
78 0
LeetCode题解:判断是否能拆分数组
LeetCode题解:判断是否能拆分数组
LeetCode-442 数组中重复的数据
LeetCode-442 数组中重复的数据
|
前端开发
前端学习案例1-数组反序&排序&乱序的方法
前端学习案例1-数组反序&排序&乱序的方法
71 0
前端学习案例1-数组反序&排序&乱序的方法