LeetCode 6.ZigZag Conversion解法思路

 原题目:

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:

P     I    N
A   L S  I G
Y A   H R
P     I

题目分析:

题干的意思是在输入一段字符串后,把字符串按照Z的写法,逆时针90度组成新的排列,最后逐行字母按顺序排序,输出一段新的字符串。

解题思路:

方法一有

1 创建行字符串,每行都创建一个数组存放对应行的字符。

2 对源字符串进行顺序循环,判断该字母是第几行的,然后把该字母,放到行数组中。

3 循环完后,把数组逐行合并到一起。

 

方法二:

使用数学规律进行排序,相对方法一是复杂度低,占用内存少。直接计算每行应该对应的字符。

1 对第一行和最后一行单独处理

     第一行和最后一行相邻字符索引相差值是2n-2;

2 对斜的字符进行单独计算

    其规律可以看出 与第一个字符索引相差 2(总行数-当前行-1)

3 对逐行进行循环。

1                7 

2          6    8

3    5          9

4               10

 

初步按照方法二编写,程序如下:

#include "stdio.h"
#include "stdlib.h"

char str[] = "PAYPALISHIRING";


char * convert(char * s, int numRows)
{
    	char *buf;
	int iCurRow;
	unsigned int i, len;
	unsigned int outIndex = 0;
	unsigned int index = 0;
	unsigned int iRowFirstIndex = 0;
	char bFirst = 1;
	
	if(numRows < 3)
		return s;
	
	i = 0;
	while(s[i] != '\0')
	{
		i++;
	}
	len = i;
	
	buf = (char *)malloc(sizeof(char)*len);
	if(NULL == buf)
		return s;
	
	for(iCurRow = 0; iCurRow < numRows; iCurRow++)
	{

		iRowFirstIndex = iCurRow;
		bFirst = 1;
		if(0 == iCurRow || numRows-1 == iCurRow)
		{

			for(index = iCurRow; index < len;)
			{
				buf[outIndex++] = s[index];
				index += 2*(numRows-1);
			}
			
		}
		else
		{
			for(index = iCurRow; index < len;)
			{
				buf[outIndex++] = s[index];
				if(1 == bFirst)
				{
					index += 2*(numRows - 1 - iCurRow);
					bFirst = 0;
				}
				else
				{
					iRowFirstIndex += 2*(numRows - 1);
					bFirst = 1;
					index = iRowFirstIndex;
				}
			}
		}
	}
    
    for(i = 0; i < len; i++)
    {
        s[i] = buf[i];
		printf("%c", buf[i]);
    }
    free(buf);
	
	return s;
}

int main(void)
{
    char *strout;
    printf("str:%s\r\n", str);
    strout = convert(str, 2);
    printf("out:%s\r\n", strout);

	return 0;
}

结果runtime:12ms 内存使用:7.9MB(花了3个多小时TT,结果有待优化) 

我看了其他人使用其他方式的计算方法

下面是python的,最快是44ms,使用内存11.6ms

这个使用C++,运行时间20ms,内存使用12.5ms 

 

 

先总结到这,虽然使用数学的计算方式,但是编程上还有优化空间。明天再补上。

 

2019/5/7 strlen的使用

使用strlen来获取字符串长度后,发现运行时间节省了4ms,而内存没有大的变化。

超过百分百了

 

 

再次提交了一下昨天的源码

 坑爹的,为啥就快了4ms,还以为是i计算长度这里耗时呢?这个只能是leetcode服务器那边的缘由了。

 

 

 

好奇strlen是如何获取字符串的长度的?

学习高效编程的有效方式之一就是阅读高质量的代码,而strlen是CRT底层函数库,分析strlen的源码看一下

看到这边文章很全面,分享一下

参考http://www.cppblog.com/ant/archive/2007/10/12/32886.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值