《算法设计与分析》第二周作业

《算法设计与分析》第二周作业

标签(空格分隔): 课堂作业


姓名:李**
学号:16340114
题目:ZigZag Conversion(https://leetcode.com/problems/zigzag-conversion/description/


题目概要

  输入一个字符串,将该字符串按类z形状排列,再按横向顺序输出新的字符串,详情点击题目链接。

思路

尝试一

  创建一个矩阵,把输入字符串按照题目规则填入矩阵中,矩阵剩余位置留空,再按行遍历矩阵,得到目的输出。这样做貌似很暴力,而且当行数增多的时候,矩阵里的空位会变得很多,且遍历的开销也会变得非常大。这种解法似乎不现实。
这里写图片描述

尝试二

  采用分而治之的思想,将按z型排列的字符串分成若干个相同的组(如图所示),在一个组内建立输入字符串与输出字符串的映射函数,继而推广到所有组别,得出通用的转换公式。

  注意到,在分组的时候,最后一组可能与其他组不同,这使得映射函数的建立变得困难,因此,先假定最后一组与其他组的模式都是相同的,之后再处理最后一组(参差不齐)的问题。

在建立转换公式之前,先计算一些重要的参数:
  每组的字符个数(靠观察可得):entitiesInSet = 2 * numRows - 2;
  总组数(同样靠观察可得):numSet = ⌈ inputString.length() / entitiesInSet ⌉(向上取整);
这里写图片描述

在每一组中,分为四种情况:

1.组内第一个字符

  稍微观察一下(感觉这题就是在找规律),每组的第一个字符对应输出字符下标为 分组序号setIndex,即

outputString[setIndex] = inputString[oldStringIndex];

这里写图片描述

2.组内第一列中间字符(除去第一个和最后一个字符)

  第二行的元素对应的下标为 【第一行的字符数 + 组号 * 2】
  第三行的元素对应的下标为 【第一行的字符数 + 第二行的字符数 + 组号 * 2】
  ···
  第i行的元素对应的下标为 【第一行的字符数 + 第二行的字符数 + ··· + 第i - 1行的字符数 + 组号 * 2】

  第一行的字符数为总组数numSet,剩余行的字符数为总组数乘二numSet * 2。

  可以得到对第一列中第i个(对应第i+1行)字符。(图中第一组的A是第1个(i = 1),Y是第二个 (i = 2))对应的下标为 【组数 * (2 * i - 1) + 组号 * 2】, 即

outputString[numSet * (2 * i - 1) + setIndex * 2] = inputString[oldStringIndex];

这里写图片描述

3.组内第一列最后一个字符

  用类似情况2的推算,对应的下标为 【除最后一行的总字符数(第一行的字符数 + 第2行 ~ 第numRows - 1行)的字符数 + 组号】,即

outputString[numSet * (2 * numRows - 3) + setIndex] = inputString[oldStringIndex];

这里写图片描述

4.组内在斜线上的元素

  与第2中情况类似,只是对应的下标多了1,组数 * (2 * i - 1) + 组号 * 2 + 1,即

outputString[numSet * (2 * i - 1) + setIndex * 2 + 1] = inputString[oldStringIndex];

这里写图片描述

  这四种情况都处理完之后,就开始处理最后一组(参差不齐)的问题。
  其实这个问题还蛮好处理的,将最后一组单独拿出来处理,先假定最后一组是完整的,与其他组一样处理,在遇到输入字符不存在的位置时,将一个特殊符号(如“*”,输入字符串里没有该符号)放入输出字符串中。将全部完成后再次遍历输出字符,遇到该特殊字符(*)时将该字符剔除,即可得到最终答案。

具体实现

  先计算“思路”中的两个重要参数。
  再以组号为参数进行循环,处理除最后一组之外的组。同时使用一个下标变量,按顺序对输入字符进行处理,每处理完一个字符该变量自增。
  在每组中按照思路中的4种情况按顺序处理,将得出的公式转化为代码即可,特别地,在第3种情况中,随着输入字符下标的递增,行数是递减的,这时只要将循环变量递减即可。
  之后处理最后一组,使用宏定义检测下标是否越界,如越界,则将‘*’输出到输出字符串。
  最后创建一个新的字符串,将中间输出字符串的非’*’字符吸收即可。

心得

  虽然这次没用到课堂上讲的大师定理,但是分治思想的应用还是使得这个问题简单了许多(比用矩阵蛮干好多了不是吗),将一个大问题分解成一个个的小问题,这样思考起来不会那么吃力,而且把小问题解决了大问题也就自然而然地就解决了。

源码:

#define entityOrBubble (oldStringIndex >= s.length() ? '*' : s[oldStringIndex]);

class Solution 
{
public:
    string convert(string s, int numRows) 
    {
        if (s.length() == 0 || numRows == 1)
            return s;

        int entitiesInSet = 2 * numRows - 2;
        int numSet = ceil( (float)s.length() / entitiesInSet );

        string tempString(numSet * entitiesInSet, '*');
        // common set
        for (int setIndex = 0; setIndex <= numSet - 2; ++setIndex)
        {
            int oldStringIndex = setIndex * entitiesInSet;

            //first entity in each set
            tempString[setIndex] = s[oldStringIndex];
            oldStringIndex++;

            //the remain entities of the first column in each set  except the last one
            for (int i = 1; i <= numRows - 2; ++i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2] = s[oldStringIndex];
                oldStringIndex++;
            }

            //the last entity of the first column in each set 
            tempString[numSet * (2 * numRows - 3) + setIndex] = s[oldStringIndex];
            oldStringIndex++;

            //the remain entities of each set
            for (int i = numRows - 2; i >= 1; --i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2 + 1] = s[oldStringIndex];
                oldStringIndex++;
            }
        }

        // the last set
        {
            int setIndex = numSet - 1;

            int oldStringIndex = setIndex * entitiesInSet;

            //first entity in each set
            tempString[setIndex] = s[oldStringIndex];
            oldStringIndex++;

            //the remain entities of the first column in each set  except the last one
            for (int i = 1; i <= numRows - 2; ++i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2] = entityOrBubble;
                oldStringIndex++;
            }

            //the last entity of the first column in each set 
            tempString[numSet * (2 * numRows - 3) + setIndex] = entityOrBubble;
            oldStringIndex++;

            //the remain entities of each set
            for (int i = numRows - 2; i >= 1; --i)
            {
                tempString[numSet * (2 * i - 1) + setIndex * 2 + 1] = entityOrBubble;
                oldStringIndex++;
            }
        }

        string finalString(tempString.length() + 1, '\0');
        int finalStringIndex = 0;
        for (int i = 0; i < tempString.length(); ++i)
        {
            if(tempString[i] != '*')
            {
                finalString[finalStringIndex] = tempString[i];
                finalStringIndex++;
            }   
        }

        return finalString;
    }
};

猜你喜欢

转载自blog.csdn.net/Ray0758/article/details/82728860