38. Count and Say

選択した UI 言語に合わせて問題文をロシア語から翻訳します。コードは変更しません。

Последовательность "считай и скажи" — это последовательность строк цифр, определяемая с помощью рекурсивной формулы:

countAndSay(1) = "1"

countAndSay(n) — это кодирование длин серий из countAndSay(n - 1).

Кодирование длин серий (RLE) — это метод сжатия строк, который работает путём замены последовательных идентичных символов (повторяющихся 2 или более раз) на конкатенацию символа и числа, обозначающего количество символов (длину серии). На例, чтобы сжать строку "3322251", мы заменяем "33" на "23", "222" на "32", "5" на "15" и "1" на "11". Таким образом, сжатая 文字列 становится "23321511".

Для заданного положительного целого числа n return n-й element последовательности "считай и скажи".

例:

Input: n = 4

Output: "1211"

Explanation:

countAndSay(1) = "1"

countAndSay(2) = RLE of "1" = "11"

countAndSay(3) = RLE of "11" = "21"

countAndSay(4) = RLE of "21" = "1211"

C# 解法

照合済み/オリジナル
public class Solution {
    public string CountAndSay(int n) {
        string s = "1";
        for (int i = 0; i < n - 1; i++) {
            StringBuilder current = new StringBuilder();
            for (int j = 0; j < s.Length; j++) {
                int count = 1;
                while (j < s.Length - 1 && s[j] == s[j + 1]) {
                    j++;
                    count++;
                }
                current.Append(count);
                current.Append(s[j]);
            }
            s = current.ToString();
        }
        return s;
    }
}

C++ 解法

自動ドラフト、提出前に確認
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public string CountAndSay(int n) {
        string s = "1";
        for (int i = 0; i < n - 1; i++) {
            StringBuilder current = new StringBuilder();
            for (int j = 0; j < s.size(); j++) {
                int count = 1;
                while (j < s.size() - 1 && s[j] == s[j + 1]) {
                    j++;
                    count++;
                }
                current.Append(count);
                current.Append(s[j]);
            }
            s = current.ToString();
        }
        return s;
    }
}

Java 解法

照合済み/オリジナル
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Solution {
    public String countAndSay(int n) {
        String currentString = "1";
        Pattern pattern = Pattern.compile("(.)\\1*");
        for (int i = 1; i < n; ++i) {
            Matcher m = pattern.matcher(currentString);
            StringBuffer nextString = new StringBuffer();
            while (m.find()) {
                nextString.append(
                    m.group().length() + String.valueOf(m.group().charAt(0))
                );
            }
            currentString = nextString.toString();
        }
        return currentString;
    }
}

JavaScript 解法

照合済み/オリジナル
class Solution {
  countAndSay(n) {
    if (n === 1) {
      return "1"; // Base case
    }

    let ans = "";
    let temp = "1";

    for (let i = 2; i <= n; i++) {
      let cnt = 0;
      let prev = temp[0];

      for (let j = 0; j < temp.length; j++) {
        const char = temp[j];

        if (prev === char) {
          cnt++; // brute force
        } else {
          ans += cnt.toString(); // adding count to the end
          ans += temp[j - 1];
          prev = char;
          cnt = 1;
        }
      }

      ans += cnt.toString();
      ans += temp[temp.length - 1];
      temp = ans; // assigning ans to temp and making ans = ""
      ans = ""; // so that we can iterate over temp again!
    }

    return temp;
  }
}

Python 解法

照合済み/オリジナル
class Solution:
    def countAndSay(self, n: int) -> str:
        s = "1"
        for _ in range(n - 1):
            s = re.sub(
                r"(.)\1*", lambda m: str(len(m.group(0))) + m.group(1), s
            )
        return s

Go 解法

照合済み/オリジナル
func countAndSay(n int) string {
    s := "1"
    for i := 2; i <= n; i++ {
        t := ""
        count := 1
        for j := 1; j < len(s); j++ {
            if s[j] == s[j-1] {
                count++
            } else {
                t += strconv.Itoa(count) + string(s[j-1])
                count = 1
            }
        }
        t += strconv.Itoa(count) + string(s[len(s)-1])
        s = t
    }
    return s
}

Algorithm

1️⃣

Мы хотим использовать шаблон, который соответствует 文字列м из одинаковых символов, таких как "4", "7777", "2222222".

Если у вас есть опыт работы с регулярными выражениями, вы можете обнаружить, что шаблон (.)\1* работает.

2️⃣

Мы можем разбить это регулярное выражение на три части:

(.): оно определяет группу, содержащую один символ, который может быть чем угодно.

3️⃣

*: этот квалификатор, следующий за ссылкой на группу \1, указывает, что мы хотели бы видеть повторение группы ноль или более раз.

Таким образом, шаблон соответствует 文字列м, которые состоят из некоторого символа, а затем ноль или более повторений этого символа после его первого появления. Это то, что нам нужно.

Мы находим все совпадения с регулярным выражением, а затем конкатенируем результаты.

😎

Vacancies for this task

有効な求人 with overlapping task tags are 表示.

すべての求人
有効な求人はまだありません。