算法(二十)

 题目链接:6. Z 字形变换 - 力扣(LeetCode)

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

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

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

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

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

string convert(string s, int numRows);

示例 1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

示例 3:

输入:s = "A", numRows = 1
输出:"A"

提示:

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

解法(模拟 + 找规律):

算法思路:

找规律,用 row 代替⾏数,row = 4 时画出的 N 字形如下:

0 2row - 2 4row - 4

1 2row - 3 2row - 1 4row - 5 4row - 3

2 2row-4 2row 4row - 6 4row - 2

3 2row + 1 4row - 1

不难发现,数据是以 2row - 2 为⼀个周期进⾏规律变换的。将所有数替换成⽤周期来表⽰的变量:

第⼀⾏的数是:0, 2row - 2, 4row - 4;

第⼆⾏的数是:1, (2row - 2) - 1, (2row - 2) + 1, (4row - 4) - 1, (4row - 4) + 1;

第三⾏的数是:2, (2row - 2) - 2, (2row - 2) + 2, (4row - 4) - 2, (4row - 4) + 2;

第四⾏的数是:3, (2row - 2) + 3, (4row - 4) + 3。

可以观察到,第⼀⾏、第四⾏为差为 2row - 2 的等差数列;第⼆⾏、第三⾏除了第⼀个数取值为⾏ 数,每组下标为(2n - 1, 2n)的数围绕(2row - 2)的倍数左右取值。

以此规律,我们可以写出迭代算法。

class Solution {
    public String convert(String s, int numRows) {
        //处理边界
        if(numRows==1){
            return s;
        }
        int d=2*numRows-2,n=s.length();
        StringBuilder ret=new StringBuilder();
        //处理第一行
        for(int i=0;i<n;i+=d){
            ret.append(s.charAt(i));
        }
        //处理中间行
        for(int k=1;k<numRows-1;k++){
            for(int i=k,j=d-i;i<n||j<n;i+=d,j+=d){
                if(i<n){
                    ret.append(s.charAt(i));
                }
                if(j<n){
                    ret.append(s.charAt(j));
                }
            }
        }
        //处理最后一行
        for(int i=numRows-1;i<n;i+=d){
            ret.append(s.charAt(i));
        }
        return ret.toString();
    }
}

 题目链接:38. 外观数列 - 力扣(LeetCode)

「外观数列」是一个数位字符串序列,由递归公式定义:

  • countAndSay(1) = "1"
  • countAndSay(n) 是 countAndSay(n-1) 的行程长度编码。

    行程长度编码(RLE)是一种字符串压缩方法,其工作原理是通过将连续相同字符(重复两次或更多次)替换为字符重复次数(运行长度)和字符的串联。例如,要压缩字符串 "3322251" ,我们将 "33" 用 "23" 替换,将 "222" 用 "32" 替换,将 "5" 用 "15" 替换并将 "1" 用 "11" 替换。因此压缩后字符串变为 "23321511"

    给定一个整数 n ,返回 外观数列 的第 n 个元素。

    示例 1:

    输入:n = 4

    输出:"1211"

    解释:

    countAndSay(1) = "1"

    countAndSay(2) = "1" 的行程长度编码 = "11"

    countAndSay(3) = "11" 的行程长度编码 = "21"

    countAndSay(4) = "21" 的行程长度编码 = "1211"

    示例 2:

    输入:n = 1

    输出:"1"

    解释:

    这是基本情况。

    提示:

    • 1 <= n <= 30

    所谓「外观数列」,其实只是依次统计字符串中连续且相同的字符的个数。依照题意,依次模拟即可。

    class Solution {
        public String countAndSay(int n) {
            String ret="1";
            for(int i=1;i<n;i++){//解释n-1次即可
                StringBuilder tmp=new StringBuilder();
                int len=ret.length();
                for(int left=0,right=0;right<len;){//len多长暂时不确定
                    while(right<len&&ret.charAt(left)==ret.charAt(right)){
                        right++;
                    }
                    tmp.append(Integer.toString(right-left));
                    tmp.append(ret.charAt(left));
                    left=right;
                }
                ret=tmp.toString();
            }
            return ret;
        }
    }

     

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值