子串翻转 (差分数组)

题目描述


小美有一个由小写字母组成的字符串。小美认为字母表很有意思。所以他规定, 在小写字母中,每个字母的后继就是字母表中这个字母的后一个 , 比如 a 的后继是 b , b 的后继是 c 。而字母表中的最后一个字母是 z , 为了防止 z 没有后继 , 小美又规定 z 的后继是 a 。这样字母的后继就形成了一个 闭环
现在小美想要让字符串发生变化。所以他 每次会给出一个 区间 和一个数 k , 并且让区间中所有的字母变成他们的第 k 个后继。第 k 个后继即让后继操作进行 k 次,比如 a 的 2 级后继是 c , a 的 26 级后继是 a 。
现在小美记下来了 操作序列和操作完之后得到的字符串 。请你 还原原来的字符串。

输入描述 :
第一行一个长度为 n (1 <= n <= 10^5) 的字符串 , 代表 操作完成 之后的字符串
第二行一个数 q (1 <= q <= 10^5) 代表操作次数
接下来 q 行 , 每行三个数 i , j , k ( 1 <= i <= j <= n , 1 <= k <= 10^9 ) , 代表区间 左右端点 和 第 k 级 后继。
输出描述:
输出一个字符串,代表操作之前小美的字符串。


样例输入:
abcdefg
3
1 3 1
2 4 1
3 5 2
样例输出:
zzyacfg
第一次操作后 : aazacfg
第二次操作后 : ababcfg
第三次操作后 : abcdefg

题目分析


此题的意思是:频繁对原始数组的某个区间的元素进行 同增 / 同减符合差分数组的应用。 对差分数组不了的 可参考 差分数组模板 。

package baidu;
import java.util.*;
public class Main25 {

    private int[] diff;
    public void getDiff(int[] nums){
        diff = new int[nums.length];
        // 构造差分数组
        diff[0] = nums[0];
        for(int i = 1 ; i < nums.length ; i ++){
            diff[i] = nums[i] - nums[i - 1];
        }
    }

    // 给闭区间 [left , right] 增加 val (可以是负数)
    public void increment(int left , int right , int val){
        diff[left] += val;
        if(right + 1 < diff.length){
            diff[right + 1] -= val;
        }
    }

    public String result(){
        int[] res = new int[diff.length];
        // 根据差分数组构造结果数组
        res[0] = diff[0];
        for(int i = 1 ; i < diff.length ; i ++){
            res[i] = res[i - 1] + diff[i];
        }
        StringBuffer sb = new StringBuffer();
        for(int i = 0 ; i < diff.length ; i ++){
         	// 正负数映射到区间 0-26 之间
            int temp = ((res[i] % 26) + 26) % 26; 
            sb.append((char) ('a' + temp));
        }
        return sb.toString();
    }

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        String str = input.nextLine();
        String num = input.nextLine();
        int n = Integer.parseInt(num);
        int len = str.length();
        int[] nums = new int[len];
        for(int i = 0 ; i < len ; i ++){
            nums[i] = str.charAt(i) - 'a';
        }
        Main25 obj = new Main25();
        obj.getDiff(nums);
        while(n -- > 0){
            String query = input.nextLine();
            String[] buff = query.split(" ");
            int left = Integer.parseInt(buff[0]);
            int right = Integer.parseInt(buff[1]);
            // 反向操作
            int val = -Integer.parseInt(buff[2]);
            obj.increment(left - 1 , right - 1 , val);
        }
        System.out.println(obj.result());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值