zoukankan      html  css  js  c++  java
  • 算法六Z自形变换

    将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

    比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:

    L    C     I     R
    E T O E S  I I G
    E    D     H   N

    之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。

    请你实现这个将字符串进行指定行数变换的函数:

    string convert(string s, int numRows);

    示例 1:

    输入: s = "LEETCODEISHIRING", numRows = 3
    输出: "LCIRETOESIIGEDHN"

    示例 2:

    输入: s = "LEETCODEISHIRING", numRows = 4
    输出: "LDREOEIIECIHNTSG"
    解释:

    L       D     R
    E   O E   I  I
    E C   I  H   N
    T      S      G

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/zigzag-conversion
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    题目看了半天,看到评论说这是N字形变换,才突然明白说的什么。给定字符串,然后按照类似于波浪一样反的N字排序,N的高度给定,然后把排序好的字符再按照横向一行行的读取出来。

    找规律,这道题有很明显的规律,按照V的形式循环,每个V的字母个数是2 * numRows - 2,因为是V,所以是两排高度,每个高度是numRows,所以是2 * numRows,因为V最底端转折的字母只需一个就够了,所以减1,V最后一个字母要算到下一个V,所以再减一。

    这样每一行的字母位置相对于V开头的字母索引是固定的,所以按照V的跳度遍历,计算每一行的字母。

        string tmp;
        if (numRows > 1 && !s.empty())
        {
            for (int i = 0; i < numRows; i++)
            {
                for (int j = 0; j < s.size(); j = j + (numRows * 2 - 2))
                {
                    if (j + i < s.size())
                    {
                        tmp.push_back(s[j + i]);
                    }
                    if ((numRows - 1 - i) * 2 < (numRows * 2 - 2) && i != numRows - 1 && (j + numRows - 1 + numRows - 1 - i < s.size()))
                    {
                        tmp.push_back(s[j + numRows - 1 + numRows - 1 - i]);
                    }
                }
            }
        }
        else
        {
            tmp = s;
        }
    
        return tmp;

    考虑到tmp在不断的push_back,导致内存存在申请释放的问题,所以进行修改,一次性把内存申请完

    string convert(string s, int numRows) {
            string tmp = s;
            int tmpi = 0;
            if (numRows > 1 && !s.empty())
            {
                for (int i = 0; i < numRows; i++)
                {
                    for (int j = 0; j < s.size(); j = j + (numRows * 2 - 2))
                    {
                        if (j + i < s.size())
                        {
                            tmp[tmpi] = s[j + i];
                            tmpi++;
                        }
                        if ((numRows - 1 - i) * 2 < (numRows * 2 - 2) && i != numRows - 1 && (j + numRows - 1 + numRows - 1 - i < s.size()))
                        {
                            tmp[tmpi] = s[j + numRows - 1 + numRows - 1 - i];
                            tmpi++;
                        }
                    }
                }
            }
    
            return tmp;
        }

    坑一,在所有的字符访问的地方都需要注意判断是不是会超过s的长度,避免越界。

    评论解一,除了上面的方法,还有另一种方法,就是根据字符串N字排序的步骤,一个个的计算。声明一个字符串数组,每一个元素表示变换后这一行的字母,那么从0开始,每次增加一行,把元素放到当前行对应的字符串数组最后,到达最底端或是最顶端的时候,字符串数组的索引就从递增或是递减变成相反的方向继续。这种效率与上面差不多,也很好理解,并且比较巧妙。

  • 相关阅读:
    CSU 1333 Funny Car Racing
    FZU 2195 检查站点
    FZU 2193 So Hard
    ZOJ 1655 FZU 1125 Transport Goods
    zoj 2750 Idiomatic Phrases Game
    hdu 1874 畅通工程续
    hdu 2489 Minimal Ratio Tree
    hdu 3398 String
    洛谷 P2158 [SDOI2008]仪仗队 解题报告
    POJ 1958 Strange Towers of Hanoi 解题报告
  • 原文地址:https://www.cnblogs.com/studywithallofyou/p/12022421.html
Copyright © 2011-2022 走看看