leetcode 880、索引处的解码字符串(Character类)

给定一个编码字符串 S。为了找出解码字符串并将其写入磁带,从编码字符串中每次读取一个字符,并采取以下步骤:

如果所读的字符是字母,则将该字母写在磁带上。
如果所读的字符是数字(例如 d),则整个当前磁带总共会被重复写 d-1 次。
现在,对于给定的编码字符串 S 和索引 K,查找并返回解码字符串中的第 K 个字母。


示例 1:

输入:S = “leet2code3”, K = 10
输出:“o”
解释:
解码后的字符串为 “leetleetcodeleetleetcodeleetleetcode”。
字符串中的第 10 个字母是 “o”。

示例 2:

输入:S = “ha22”, K = 5
输出:“h”
解释:
解码后的字符串为 “hahahaha”。第 5 个字母是 “h”。

示例 3:

输入:S = “a2345678999999999999999”, K = 1
输出:“a”
解释:
解码后的字符串为 “a” 重复 8301530446056247680 次。第 1 个字母是 “a”。

提示:

  • 2 <= S.length <= 100
  • S 只包含小写字母与数字 2 到 9 。
  • S 以字母开头。
  • 1 <= K <= 10^9
  • 解码后的字符串保证少于 2^63 个字母。

思路:

第一反应是将字符串展开后再进行后续工作,但假设有样例:t263w789e4562 这种情况的话会发生内存溢出。

所以换个思路:

因为我们是从最终展开完后的字符串中找的,而不管怎么展开,我们所需要返回的值一定会在原始的字符串S中,因此我们没有必要把S展开后再求。

核心的基本原理:假设我们有一个像 appleappleappleappleappleapple(apple 重复5次) 这样的解码字符串和一个像 K=24 这样的索引,那么如果 K=4,答案是相同的(都是 l)。

不失一般性地,当解码的字符串等于某个长度为 x 的单词(或句子)重复某些次数时,索引 K % x 的答案与索引 K 的答案相同。

所以我们的目的是要使最终的字符串缩小范围回到我们需要找的字符出现的第一个子字符串内,

有点抽象,举个例子:

输入:S = “leet2code3”
那么解码后的字符串为 “leetleetcodeleetleetcodeleetleetcode”。

如果 K = 10(此时需要找的是 “o”),那么就让字符串缩小至 “leetleetcode” 这个子字符串内(这是整个解码字符串中第一次出现 “o” 的子字符串),

同理如果 K = 2,那么就让字符串缩小至 “leet” 这个区间内。

所以我们缩小字符串范围时停止的条件是 K % size == 0(缩小至第一个出现的子字符串)。

因此有算法:
1、先算出展开后的S的长度为size,
2、倒序遍历,遇见数字size = size / 数字,遇见字母size = size - 1,直至 K % size == 0。


知识点:

Character 类用于对单个字符进行操作。

Character 类在对象中包装一个基本类型 char 的值。

将一个char类型的参数传递给需要一个Character类型参数的方法时,那么编译器会自动地将char类型参数转换为Character对象。 这种特征称为装箱,反过来称为拆箱。

// 原始字符 'a' 装箱到 Character 对象 ch 中
Character ch = 'a';
 
// 原始字符 'x' 用 test 方法装箱
// 返回拆箱的值到 'c'
char c = test('x');

以下方法都是 boolean 型:
isLetter() 是否是一个字母
isDigit() 是否是一个数字字符

isWhitespace() 是否是一个空白字符

isUpperCase() 是否是大写字母
isLowerCase() 是否是小写字母

toUpperCase() 指定字母的大写形式
toLowerCase() 指定字母的小写形式

toString() 返回字符的字符串形式,字符串的长度仅为1


class Solution {
    public String decodeAtIndex(String S, int K) {
        long size = 0;  //用long
        
        for (int i = 0; i < S.length(); i++) {  //展开字符串的过程中只记录总长度,不记录字符串本身
            char c = S.charAt(i);
            if (Character.isDigit(c))
                size *= c - '0';    //将字符转化为数字
            else 
                size++;
        }
        
        for (int i = S.length() - 1; i >= 0; i--) {
            char c = S.charAt(i);
            K %= size;
            if (K == 0 && Character.isLetter(c))
                return Character.toString(c);
            if (Character.isDigit(c))
                size /= c - '0';
            else 
                size--;
        }
        
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值