Skip to content

Files

This branch is 2 commits ahead of, 267 commits behind doocs/leetcode:main.

3412.Find Mirror Score of a String

comments difficulty edit_url
true
中等

English Version

题目描述

给你一个字符串 s

英文字母中每个字母的 镜像 定义为反转字母表之后对应位置上的字母。例如,'a' 的镜像是 'z''y' 的镜像是 'b'

最初,字符串 s 中的所有字符都 未标记 

字符串 s 的初始分数为 0 ,你需要对其执行以下过程:

  • 从左到右遍历字符串。
  • 对于每个下标 ,找到距离最近的 未标记 下标 j,下标 j 需要满足 j < is[j]s[i] 的镜像。然后 标记 下标 ij,总分加上 i - j 的值。
  • 如果对于下标 i,不存在满足条件的下标 j,则跳过该下标,继续处理下一个下标,不需要进行标记。

返回最终的总分。

 

示例 1:

输入: s = "aczzx"

输出: 5

解释:

  • i = 0。没有符合条件的下标 j,跳过。
  • i = 1。没有符合条件的下标 j,跳过。
  • i = 2。距离最近的符合条件的下标是 j = 0,因此标记下标 0 和 2,然后将总分加上 2 - 0 = 2 。
  • i = 3。没有符合条件的下标 j,跳过。
  • i = 4。距离最近的符合条件的下标是 j = 1,因此标记下标 1 和 4,然后将总分加上 4 - 1 = 3 。

示例 2:

输入: s = "abcdef"

输出: 0

解释:

对于每个下标 i,都不存在满足条件的下标 j

 

提示:

  • 1 <= s.length <= 105
  • s 仅由小写英文字母组成。

解法

方法一:哈希表

我们可以用一个哈希表 d 来存储每个未标记的字符的下标列表,其中键是字符,值是下标列表。

我们遍历字符串 s ,对于每个字符 x ,我们找到其镜像字符 y ,如果 d 中存在 y ,我们就取出 y 对应的下标列表 ls ,取出 ls 的最后一个元素 j ,并将 j ls 中移除。如果 ls 变为空,我们就将 y d 中移除。此时,我们就找到了一个满足条件的下标对 ( j , i ) ,并将 i j 加到答案中。否则,我们将 x 加入到 d 中。

时间复杂度 O ( n ) ,空间复杂度 O ( n ) 。其中 n 为字符串 s 的长度。

Python3

class Solution:
    def calculateScore(self, s: str) -> int:
        d = defaultdict(list)
        ans = 0
        for i, x in enumerate(s):
            y = chr(ord("a") + ord("z") - ord(x))
            if d[y]:
                j = d[y].pop()
                ans += i - j
            else:
                d[x].append(i)
        return ans

Java

class Solution {
    public long calculateScore(String s) {
        Map<Character, List<Integer>> d = new HashMap<>(26);
        int n = s.length();
        long ans = 0;
        for (int i = 0; i < n; ++i) {
            char x = s.charAt(i);
            char y = (char) ('a' + 'z' - x);
            if (d.containsKey(y)) {
                var ls = d.get(y);
                int j = ls.remove(ls.size() - 1);
                if (ls.isEmpty()) {
                    d.remove(y);
                }
                ans += i - j;
            } else {
                d.computeIfAbsent(x, k -> new ArrayList<>()).add(i);
            }
        }
        return ans;
    }
}

C++

class Solution {
public:
    long long calculateScore(string s) {
        unordered_map<char, vector<int>> d;
        int n = s.length();
        long long ans = 0;
        for (int i = 0; i < n; ++i) {
            char x = s[i];
            char y = 'a' + 'z' - x;
            if (d.contains(y)) {
                vector<int>& ls = d[y];
                int j = ls.back();
                ls.pop_back();
                if (ls.empty()) {
                    d.erase(y);
                }
                ans += i - j;
            } else {
                d[x].push_back(i);
            }
        }
        return ans;
    }
};

Go

func calculateScore(s string) (ans int64) {
	d := make(map[rune][]int)
	for i, x := range s {
		y := 'a' + 'z' - x
		if ls, ok := d[y]; ok {
			j := ls[len(ls)-1]
			d[y] = ls[:len(ls)-1]
			if len(d[y]) == 0 {
				delete(d, y)
			}
			ans += int64(i - j)
		} else {
			d[x] = append(d[x], i)
		}
	}
	return
}

TypeScript

function calculateScore(s: string): number {
    const d: Map<string, number[]> = new Map();
    const n = s.length;
    let ans = 0;
    for (let i = 0; i < n; i++) {
        const x = s[i];
        const y = String.fromCharCode('a'.charCodeAt(0) + 'z'.charCodeAt(0) - x.charCodeAt(0));

        if (d.has(y)) {
            const ls = d.get(y)!;
            const j = ls.pop()!;
            if (ls.length === 0) {
                d.delete(y);
            }
            ans += i - j;
        } else {
            if (!d.has(x)) {
                d.set(x, []);
            }
            d.get(x)!.push(i);
        }
    }
    return ans;
}