1. 程式人生 > >LeetCode題828 —— Unique Letter String

LeetCode題828 —— Unique Letter String

values ice pear enc 有趣 only value HERE font

https://leetcode.com/problems/unique-letter-string/description/

A character is unique in string S if it occurs exactly once in it.

For example, in string S = "LETTER", the only unique characters are "L" and "R".

Let‘s define UNIQ(S) as the number of unique characters in string S.

For example, UNIQ("LETTER") = 2

.

Given a string S with only uppercases, calculate the sum of UNIQ(substring) over all non-empty substrings of S.

If there are two or more equal substrings at different positions in S, we consider them different.

Since the answer can be very large, return the answer modulo 10 ^ 9 + 7.

Example 1:

Input: "ABC"
Output: 10
Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC".
Evey substring is composed with only unique letters.
Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10

Example 2:

Input: "ABA"
Output: 8
Explanation: The same as example 1, except uni("ABA") = 1.

分析

看了discuss,大神的思維和我等常人就是不一樣,跪服。首先以字符串XAXAXXAX為例,如果將第二個 A 變成唯一的character的話,只可能時某個唯一的substring包含了這個A。比如:

We can take "XA(XAXX)AX" and between "()" is our substring.

利用這種方式,可以使得第二個A成為唯一的character,那麽從上可知我們要做的是:

We can see here, to make the second "A" counted as a uniq character, we need to:

  1. insert "(" somewhere between the first and second A
  2. insert ")" somewhere between the second and third A

For step 1 we have "A(XA" and "AX(A", 2 possibility.
For step 2 we have "A)XXA", "AX)XA" and "AXX)A", 3 possibilities.

So there are in total 2 * 3 = 6 ways to make the second A a unique character in a substring.
In other words, there are only 6 substring, in which this A contribute 1 point as unique string.

現在逆轉下思維,一開始的思維是在原字符串的所有子串中尋找可能的唯一的character,我們現在就直接在S中來計算每個字符,看看對於每個unique char總公有多少種不同的找法。換而言之就是,對於S中的每個字符,如果他作為unique char的話,那麽包含他的substring的範圍是在前一個相同字符以及後一個相同字符這個區間內找的(參見上面的A),將所有可能的substring數量加起來即可,很有趣的逆向思維。

Explanation:

  1. index[26][2] record last two occurrence index for every upper characters.
  2. Initialise all values in index to -1.
  3. Loop on string S, for every character c, update its last two occurrence index to index[c].
  4. Count when loop. For example, if "A" appears twice at index 3, 6, 9 seperately, we need to count:
    • For the first "A": (6-3) * (3-(-1))"
    • For the second "A": (9-6) * (6-3)"
    • For the third "A": (N-9) * (9-6)"

代碼

  public int uniqueLetterString(String S) {
    int[][] index = new int[26][2];
    for (int i = 0; i < 26; ++i) Arrays.fill(index[i], -1);
    long res = 0, N = S.length(), mod = (int) Math.pow(10, 9) + 7;
    for (int i = 0; i < N; i++) {
      int c = S.charAt(i) - ‘A‘;
      res = res + (i - index[c][1]) * (index[c][1] - index[c][0]);
      index[c] = new int[]{index[c][1], i};
    }
  // 計算最後的c
for (int c = 0; c < 26; ++c) res = res + (N - index[c][1]) * (index[c][1] - index[c][0]); return (int) (res % mod); }

LeetCode題828 —— Unique Letter String