[杨小白]_leetcode_第85场双周赛-第三题2381. 字母移位 II

140 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标300题,记录从0到1的全过程!!

第85场双周赛-力扣

第85场双周赛-力扣

啊真是服了,1,2题合起来十分钟就ac了,第三题一直超时,也意识到问题了,最后想到了解决方法,做完提交的时候已经12点01了,差点三题选手。

2381. 字母移位 II

给你一个小写英文字母组成的字符串 s 和一个二维整数数组 shifts ,其中 shifts[i] = [starti, endi, directioni] 。对于每个 i ,将 s 中从下标 starti 到下标 endi (两者都包含)所有字符都进行移位运算,如果 directioni = 1 将字符向后移位,如果 directioni = 0 将字符向前移位。

将一个字符 向后 移位的意思是将这个字符用字母表中 下一个 字母替换(字母表视为环绕的,所以 'z' 变成 'a')。类似的,将一个字符 向前 移位的意思是将这个字符用字母表中 前一个 字母替换(字母表是环绕的,所以 'a' 变成 'z' )。

请你返回对 s 进行所有移位操作以后得到的最终字符串。

示例 1

  • 输入:s = "abc", shifts = [[0,1,0],[1,2,1],[0,2,1]]
  • 输出:"ace"
  • 解释:首先,将下标从 0 到 1 的字母向前移位,得到 s = "zac" 。
  • 然后,将下标从 1 到 2 的字母向后移位,得到 s = "zbd" 。
  • 最后,将下标从 0 到 2 的字符向后移位,得到 s = "ace" 。

示例 2

  • 输入:s = "dztz", shifts = [[0,0,0],[1,1,1]]
  • 输出:"catz"
  • 解释:首先,将下标从 0 到 0 的字母向前移位,得到 s = "cztz" 。
  • 最后,将下标从 1 到 1 的字符向后移位,得到 s = "catz" 。

提示:

  • 1 <= s.length, shifts.length <= 5 * 104
  • shifts[i].length == 3
  • 0 <= starti <= endi < s.length
  • 0 <= directioni <= 1
  • s 只包含小写英文字母。

2.解法一

这个题的思路并不难,首先按照其要求的循环遍历就可以实现这个功能。但是作为第三题哪还没有点坑呢,肯定有用例会超时的。

直接按照题目要求,进行循环位移。最后超时,通过37/39的用例。

image.png

class Solution {
    public String shiftingLetters(String s, int[][] shifts) {
        char[] chars = s.toCharArray();
        for(int i = 0; i < shifts.length; i++) {
            fun(chars, shifts[i]);
            // System.out.printlnn(Arrays.tostring(chars));
        }
        return new String(chars);
    }
    public void fun(char[] chars, int[] shift) {
        int start = shift[0];
        int end = shift[1];
        int type = shift[2];
        if(shift[2] == 0) {
            for(int i = start; i <= end; i++) {
                chars[i] = qian(chars[i]);
            }
        } else {
            for(int i = start; i <= end; i++) {
                chars[i] = hou(chars[i]);
            }
        }
    }
    public char qian(char c) {
        if(c == 'a') {
            return 'z';
        } else {
            return (char)(c - 1);
        }
    }
    public char hou(char c) {
        if(c == 'z') {
            return 'a';
        } else {
            return (char)(c + 1);
        }
    }
}

2.解法二

这里我在两个地方进行了优化

优化一,在fun函数中,如果改变的次数为n,并不会直接去改变n次,而是先将n%26后,进行位移。

优化二(第一种),用了一个move数组,记录每个位置的字符要改变的值(正数代表后移,负数代表前移)也是会超时,其实这个方法和解法一并没有太多的区别,解法一是直接改变字符,优化后是先累计,后一起改变。

优化二(最终版)还是用了move数组记录了位于i前面的字符需要位移的值,而后,用sum数组记录位于i的字符需要位移的值。再进行位移,这样时间复杂度就降低多了。

class Solution {
    public String shiftingLetters(String s, int[][] shifts) {
        char[] chars = s.toCharArray();
        int[] move = new int[chars.length];
        for(int i = 0; i < shifts.length; i++) {
            if(shifts[i][2]==0) {
                int start = shifts[i][0];
                if(start > 0) {
                    move[start - 1]++;
                }
                move[shifts[i][1]]--;
            } else {
                int start = shifts[i][0];
                if(start>0) {
                    move[start - 1]--;
                }
                move[shifts[i][1]]++;
            }
        }
        int sum = 0;
        for(int i = 0; i < move.length; i++) {
            sum = sum + move[i];
        }
        int[] move2 = new int[chars.length];
        for(int i = 0; i < move2.length; i++) {
            move2[i] += sum;
            sum = sum - move[i];
        }
        for(int i = 0; i < chars.length; i++) {
            chars[i] = fun(chars[i], move2[i]);
        }
        return new String(chars);
    }
    public char fun(char element, int move) {
        if(move == 0) return element;
        if(move > 0) {
            move = move % 26;
            char temp = (char)(element + move);
            while(temp > 'z') {
                temp = (char)(temp - 26);
            }
            return temp;
        } else {
            move = (0 - move) % 26;
            char temp = (char)(element - move);
            while(temp < 'a') {
                temp = (char)(temp + 26);
            }
            return temp;
            
        }
    }
}

image.png

解析

令我十分伤心的是,提交的时候已经00点00了,没算上分,真是哭死

image.png

第一题链接如下

[杨小白]_leetcode_第85场双周赛-第一题2379. 得到 K 个黑块的最少涂色次数

第二题链接如下

[杨小白]_leetcode_第85场双周赛-第二题2380. 二进制字符串重新安排顺序需要的时间

3.结束

差点三题选手,真是哭了,下次一定下次一定,gogogo,刷题刷题,每天一道,三年1000道!!!!