LeetCode_6
问题:
6. Z字形变换
链接:https://leetcode-cn.com/problems/zigzag-conversion/description/
分析:
A 仿真方法
直接模拟整个过程,首先根据字符串大小和行数确定整体所在的行和列,初始化为某一个用不到的字符,比如#,然后按照给定的规则,即Z字型填充,填充完成后每行的结果剔除掉占位符#,重组为最终结果即可。
其中:
1.行数numRows,则2*numRows-1为一个周期,行号上先向下递增,到numRows后向上递减,列号上前面numRows个相同,后面递增
2.每个周期为一组,则groupsize=2*numRows-1,groupwidth=1 + numRows - 2
B 数学方法
按照数字写下了后可以发下如下规律:
| 0 | 8 | 16 | 24 | |||||||||||
| 1 | 7 | 9 | 15 | 17 | 23 | 26 | ||||||||
| 2 | 6 | 10 | 14 | 18 | 22 | 27 | 31 | |||||||
| 3 | 5 | 11 | 13 | 19 | 21 | 28 | 30 | |||||||
| 4 | 12 | 20 | 29 |
1.行与行之间没有影响关系,比如上表中,5在4的右上方和正上方没有区别
2.对于行数numRows,第一行都是坐标为2*(numRows-1)的整数倍,即假设用vector<string> tmp 存储临时的每一行数据,则对于所有的j%(2*numRows-1)==0,s[j]在tmp[0]中
3.类似的,如果余数±m,则在tmp[m]中,比如对于7和9,对8求模可以视为±1,都在tmp[1]中。
4.简化一下,numRows行,对于str中的第i个元素,则满足:
如果mod1=i%(2*numRows-2)<=numrows-1,则在tmp[mod1]行
否则在tmp[2*numRows-2-mod1]行
AC Code:
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1)
{
return s;
}
string ret = "";
int length = s.size();
int col = GetColumn(length,numRows);
//char chars[][] = new char[numRows][col];
string initstr = "";
for (int i = 0; i < col; i++)
{
initstr += "#";
}
vector<string> tmp(numRows,initstr);
int groupsize = 2 * numRows - 2; //一组的个数,一整列整列减去2
int groupwidth = 1 + numRows - 2; //本身一列,去掉头尾各占一列
if (s.size() <= groupsize)
{
FileGroup(tmp, s, 0);
}
else
{
string tmpstr = "";
int index = 0;
int rolnum = 0;
while (true) //每次取一组处理
{
if (index+ groupsize >= s.size())
{
tmpstr = s.substr(index, s.size() - index);
FileGroup(tmp, tmpstr, rolnum);
break;
}
tmpstr = s.substr(index, groupsize);
FileGroup(tmp, tmpstr, rolnum);
index += groupsize;
rolnum += groupwidth;
}
}
for (int i = 0; i < tmp.size(); i++)
{
ret += GenerateStrs(tmp[i]);
}
return ret;
}
string GenerateStrs(string str)
{
string ret = "";
for (int i = 0; i < str.size(); i++)
{
if (str[i] != '#')
{
ret += str[i];
}
}
return ret;
}
void FileGroup(vector<string>& data, string str, int begin)
{
int linenum = 0;
int rowlinumber = begin;
int direction = 1;
for (int i = 0; i < str.size(); i++)
{
if (direction == 1)
{
data[linenum][rowlinumber] = str[i];
linenum += direction;
}
else
{
data[linenum][rowlinumber] = str[i];
linenum += direction;
rowlinumber++;
}
if (linenum == data.size() - 1)
{
direction = -1;
}
}
}
int GetColumn(int size, int rows)
{
int ret = 1;
if (size <= rows)
{
ret = 1;
return ret;
}
int groupsize = 2 * rows - 2; //一组的个数,一整列整列减去2
int groupwidth = 1 + rows - 2; //本身一列,去掉头尾各占一列
if (size <= groupsize)
{
ret = groupwidth - (groupsize - size);
return ret;
}
ret = size / groupsize * groupwidth + GetColumn(size%groupsize, rows);
return ret;
}
};
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1)
{
return s;
}
string ret = "";
vector<string> tmp(numRows);
for (int i = 0; i < s.size(); i++) //以2*(numRows-1)+1为周期
{
if (i % (2*numRows-2 )<=(numRows-1) ) //向下
{
tmp[i % (2 * numRows -2)] +=s[i];
}
else //向上
{
tmp[2*numRows-2- i % (2 * numRows -2)] += s[i];
}
}
for (int i = 0; i < numRows; i++)
{
ret += tmp[i];
}
return ret;
}
};
其他:
1.难得回来早一点,https://my.youdias.xin/tools/chooser.html 上随机决定做一道LeetCode,就按顺序做了这个,看到题目的第一反应就是模拟过程来处理,写code的过程中感觉到应该是有规律的,完成仿真过程后提交,战胜18.59%,实现数学方法,战胜68.61%,计算机思维是把双刃剑,如果想要提高效率,还是得用脑子。
2.用时最短的code
static const auto io_sync_off = []()
{
// turn off sync
std::ios::sync_with_stdio(false);
// untie in/out streams
std::cin.tie(nullptr);
return nullptr;
}();
class Solution {
public:
string convert(string s, int numRows) {
if(numRows == 1) return s;
int size = (numRows<<1) - 2;
char res[s.size()+1];
int index = 0;
for(int i = 0; i < numRows; i++){
for(int j = i; j < s.size(); j += size){
res[index++] = s[j];
int tmp = j + size - (i<<1);
//j是前一个黑色元素在原数组中的下标,i是画成之字形时的行数
if(i > 0 && i < numRows-1 && tmp <s.size()){
res[index++] = s[tmp];
}
}
}
res[s.size()] = '\0';
return res;
}
};
LeetCode_6的更多相关文章
- Leetcode_6. Zigzag convertion
6. Zigzag convertion 对输入的字符串做锯齿形变换,并输出新的字符串,所谓zigzag变化如下图所示. 将"ABCDEFGHIJKL"做4行的锯齿变换,新的字符串 ...
随机推荐
- Domination
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ , f ...
- IOS 打包提示错误(ERROR ITMS-90125: ERROR ITMS-90087: ERROR ITMS-90209:)
提示这种错误是集成环信造成的,解决方法看环信的官方文档: 集成动态库上传AppStore 由于 iOS 编译的特殊性,为了方便开发者使用,我们将 i386 x86_64 armv7 arm64 几个平 ...
- XmlSerilizer序列化出错时,不妨考虑BinaryFormatter
当你使用XmlSerilizer序列化一个结构复杂的类型时出现反射出错 XmlSerilizer并不会告诉你哪个字段属性或者嵌套的字段属性不能被序列号,面对多年前的代码逐一排查很恼人使用BinaryF ...
- Column 'xxx' in field list is ambiguous
一 其实看一下ambiguous的翻译就好了 一开始我觉得是含糊什么的,后来找了下才知道应该是双关... 二 所以翻译过来就是 : 列'XX'在字段列表中双关 其实就是两张表有相同的字段,但是使用时, ...
- 求一个极大数的欧拉函数 phi(i)
思路: 因为当n>=1e10的时候,线性筛就不好使啦.所以要用一个公式 φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn) 证明详见:<公式 ...
- MyBatis学习总结(三)---映射文件及引入方式
MyBatis的强大,主要原于它强大映射功能,相对其它的jdbc,使用MyBatis,你会发现省掉很多代码.上一篇已经简单做出一个实例.今天就了解一下MyBatis的映射xml文件. 了解上一篇fri ...
- 关于死循环while(true){}或for(;;){}的总结
关于死循环while(true){}或for(;;){}的总结 1.基本用法: while(true){ 语句体; } for(;;){ 语句体; } 以上情况,语句体会一直执行. 2 ...
- 【Android】ContentProvider
转载地址:http://www.cnblogs.com/lqminn/archive/2012/10/16/2725624.html 一.ContentProvider的概念 ContentProvi ...
- eclipse、idea安装lombok插件
今天新项目中,用到了lombok知识,很方便. 但是使用之前,需要在eclipse.idea中安装插件才可以使用,配置如下. 一:在开发工具中安装插件: Eclipse: 下载地址:https:// ...
- uvm_mem——寄存器模型(十二)
看完了寄存器,再来看看存储器: //------------------------------------------------------------------------------ // ...