leetcode880. 索引处的解码字符串

题目:https://leetcode-cn.com/problems/decoded-string-at-index/

思路:

看到 数据范围 "解码后的字符串保证少于 2^63 个字母",单纯地拼接字符串不实际,即使不考虑时间问题,就连内存也会爆掉,所以应该是找规律,找规律最基本的就是找循环节(比如说abc3d4,其中有"a","ab" , "abc","abc abc abc","abc abc abcd","abcabcabcd....abcabcabcd" 六个循环节,后一个循环节是由前一个循环节得到的)。

循环节跟我们要求的第K位的字符有什么关系?因为,最终得到的字符串的每一个字符  就是 某个循环节中的一个字符(因为最终的字符串都是由 循环节不断循环循环得到的.),自然第K个字符,也是某个循环节的一个字符,我们要确定第K个字符最先出现在哪个循环节,我们就能得出这个字符是什么,分两步就可以求出结果

第一步:求出每个循环节长度放到数组arr[],和 每个循环节对应的最后一个字符放到数组recordChar[]

定义一个 int arr[] , arr[i] 表示前i个字符的循环节长度。recordChar[]记录该循环节的最后一个字符。

那么 "abc3d4" 的arr数组就是 arr[] = [1,2,3,9,10,40], recordChar[] = ['a','b','c','c','d','d'];

i=0 "a" 循环1次,所以循环节长度arr[0]=1,recordChar[0]='a'; i=1  "ab"循环一次,循环节长度arr[1]=2,recordChar[1]='b';

i=2 "abc" 循环1次,循环节长度arr[2]=3,recordChar[2]=‘c’; i=3  "abc" 循环3次, 循环节长度 arr[3] = arr[2]*3 =9,recordChar[3]=recordChar[2]='c';

i=4 "abc3"循环3次加上"d",循环节长度arr[4] = arr[3]+1 = 10,recordChar[4]='d';

i=5 "abc3d"循环4次,循环节长度arr[5] = arr[4]*4 = 40,recordChar[5]='d';

第二步:根据K的值,确定K位置的这个字符最先出现在哪个循环节中,这个循环节最后一个字符就是我们要求的字符。

很明显,字符 ch 最先出现在哪个循环节,那么这个循环节的最后一个字符一定是 ch ,仔细想想。

前面的例子S = "abc3d4",我们已经得出:arr[]=[1,2,3,9,10,40],recordChar[] = ['a','b','c','c','d','d'];

比如说 'a' 这个字符就是最开始出现在arr[0]这个循环节 , 所以recordChar[0] = 'a';字符'd'最开始出现在arr[4]这个循环节中,所以recordChar[4] = 'd'。

现在我要求S = "abc3d4"  K=13的字符:

从后往前(40->10->....->1)遍历数组arr[]=[1,2,3,9,10,40],recordChar[] = ['a','b','c','c','d','d']; 

从arr[5]开始遍历,长度比K大的循环节全部跳过(因为我们要知道K最先出现在哪个循环节!K=13 的字符一定存在于arr[5]=40这个循环节中,而arr[5]是由 arr[4]得到的,那么我们可以进一步缩小范围,走到arr[4] .....,直到我们找到arr[i]<=K的情况),

接下来找到arr[4]=10 (此时K>=arr[4]),

求余:K=K%arr[4]=3,K!=0 ,说明不是这个循环节最后一个字符record[4]='d',应该是更前面的循环节,所以可以缩小范围"abc3"(本来是"abc3d",现在缩小范围"abc3"),继续寻找;

此时问题转化为:我们要求 S="abc3" K=3的字符,同样地,

我们只需要 继续往前遍历,找到 arr[2]=3 (K>=arr[2]) , K=K%arr[2] = 0,说明最先出现在arr[2]这个循环节,字符就是recordChar[2] , 所以 位置 K=13 对应的字符  就是 recordChar[2] = 'c'; 答案就是'c' 。

class Solution {
        public String decodeAtIndex(String S, int K) {
            long k = K;
            int len = S.length();
            long arr[] = new long [len];
            
            char recordChar [] = new char [len];
            
            arr[0] = 1;
            recordChar[0] = S.charAt(0);
            
            int i = 1;
            long c = 1;
            for(;i<len;i++)
            {
                char tmp = S.charAt(i);
                if(tmp>='a' && tmp<='z'){
                    c = (c+1l);
                    arr[i] = c;
                    recordChar[i] = tmp;
                }else{
                    c = c*(tmp-'0');
                    arr[i] = c;
                    recordChar[i] = recordChar[i-1];
                }
            }
            i = i - 1;
            
            String rs = "";
            while(i>=0)
            {
                if(k>=arr[i])
                {
                    k = k % arr[i];
                    if(k==0)
                    {
                        rs =  recordChar[i]+"";
                        break;
                    }
                }
                i--;
            }
            return rs;
        }
    }

我想尽力讲清楚,可能导致有些部分冗余了,如果看不懂,可以查阅其他题解,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值