6.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

分析:

所谓Z字形即也可说是倒N形,将字符串按下标顺序排列成一个个倒N形。思路用numRows个数组来表示每一行该有的元素,最终结果则是遍历这numRows个数组,而Z字形的规律也很容易找到,可将其分为两部分:1.倒N的一竖,翻译成程序即为numRows个数组每个都依次(正序)添加一个元素。2.倒N的一瞥,翻译成程序即为从numsRows-2到1的数组依次(逆序)添加一个元素。最后程序的终止原字符串遍历完。然后依次输出各个数组元素。

代码:

    public static String convert(String s, int numRows) {
        char[] a = s.toCharArray();
        char[][] b = new char[numRows][a.length];
        int [] len = new int[numRows];
        int index=0;
        while(index<a.length) {
        	for(int i=0;i<numRows&&index<a.length;i++) {
        		b[i][len[i]++] = a[index++];
        	}
        	for(int i=numRows-2;i>0&&index<a.length;i--) {
        		b[i][len[i]++] = a[index++];
        	}
        }
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<numRows;i++) {
        	for(int j=0;j<len[i];j++) {
        		sb.append(b[i][j]);
        	}
        }
        return sb.toString();
    }

优化:

采用找规律的方式也能够很容易找到每一行字符下标的规律。

(1)第一行和第numRows行属于特殊情况,他们只出现在倒N的一竖上,顺序跳跃查找,例如第一行,初始i=0,查找a[i](a为原字符串s所对应的字符数组),然后i = i + 2 * (numRows - 1);

  (2)  居于第一行和第numRows中间的行,由于他们在倒N的一竖和一瞥上均有元素,一竖上的元素下标递增方式为

i + 2 * (numRows - 1),由一竖找到下一个一瞥的方式为i + 2 * (numsRows - i - 1);

代码:

	public static String convert1(String s, int numRows) {
		if(numRows==1) {
			return s;
		}
		char[] a = s.toCharArray();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < numRows; i++) {
			int p = i;
			while (p < a.length) {
				sb.append(a[p]);
				if (i != 0 && i != numRows-1 && (p + 2 * (numRows - i - 1))<a.length) {
					sb.append(a[p + 2 * (numRows - i - 1)]);
				}
				p = p + 2 * (numRows - 1);	
			}
		}
		return sb.toString();
	}

注意:上边(1)中公式i = i + 2 * (numRows - 1),当numRows==1时i不会增加,所以需要在这种算法中判断numRows==1.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值