leetcode_力扣_6. Z 字形变换

题目描述

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
picture

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例

  • 示例 1:

输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”

  • 示例 2:
    在这里插入图片描述

  • 示例 3:

输入:s = “A”, numRows = 1
输出:“A”

提示:

  • 1 <= s.length <= 1000
  • s 由英文字母(小写和大写)、‘,’ 和 ‘.’ 组成
  • 1 <= numRows <= 1000

解题思路

  • 应该可以使用数学方法解题,即推导出各个字符的位置,运用逻辑判断使用不同的计算公式,但是我没有使用这种方法。
  • 使用二维数组辅助存储,计算过程结束后,遍历数组,取出要返回的字符串;
  • 首先先定义好合适大小的数组;
  • 分析字符的分布规律

先将题目给出的示例二维数组分布沿二四象限做翻转,可以很直接的看出分布规律:
a. 首先向右正常填充;
b. 当到达最右边界时,向左填充,此时每向左填充一个字符,同时向下移动一行;

  • 得到填充完后二维数组,将要返回的字符串取出并返回。

代码

class Solution {
public:
    string convert(string s, int numRows) {

        int s_len = s.length();
        if(s_len == 1) return s;	// 数组长度为一,直接返回
        if(numRows == 1) return s;	// 给定行数为一,也直接返回
		// 确定二维数组的行和列
        int col = numRows;
        // int row = s_len / (3 * numRows - 2) * numRows + numRows;	// 此时会发生内存越界
        int row = s_len;	// 这个不会,还是没想清楚原因

		// 初始化二维数组,也可以定义为 char 数组,更节省内存
        int **arr;
        arr = new int*[row];
        int i = 0;
        for(i = 0; i < row; i++){
            arr[i] = new int[col];
            memset(arr[i], 0, sizeof(int) * col);
        }
        // cout << "s_len = " << s_len << endl;
        // cout << "row = " << row << ", col = " << col << endl;

        int index = 0;
        int col_ = 0;
        int row_ = 0;
        int right = 1;	// 初始方向,向右填充

        while(index < s_len){
        	// 向右填充
            if(right && col_ < col){
                // if(index > 100)
                //     cout << row_ << ":" << col_ << ":" << index << " ";
                arr[row_][col_++] = s[index++];
            }else if(right){	// 当向右填充到边界时,改变方向
                right = 0;	// right = 0,表示向左;= 1 表示向右
                row_++;
                col_ -= 2;
            }
			
			// 向左填充
            if(!right && col_ >= 0){
                // if(index > 100)
                //     cout << row_ << ":" << col_ << ":" << index << " ";
                arr[row_++][col_--] = s[index++];
            }else if(!right){	// 变向
                right = 1;
                row_--;
                col_ += 2;
            }
        }

        string ret = "";
        int j = 0;
        // 注意遍历的起始位置以及方向
        for(i = 0; i < col; i++){
            for(j = 0; j < row; j++){
                if(arr[j][i] != 0){	// 对应位置不为 '0',即取出
                    ret += arr[j][i];
                }
            }
        }


        // for(i = 0; i < row; i++){
        //     for(j = 0; j < col; j++){
        //         printf("%c  ", arr[i][j]);
        //     }
        //     cout << endl;
        // }

        return ret;

    }
};

提交结果

picture

总结

明明是简简单单的逻辑小游戏,但是直接用了 暴力模拟 的方法解决,耗时和内存感人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值