93. Restore IP Addresses

선택한 UI 언어에 맞게 문제 텍스트를 러시아어에서 번역합니다. 코드는 변경하지 않습니다.

Сообщение, содержащее буквы от A до Z, можно закодировать в числа с использованием следующего соответствия:

- 'A' -> "1"

- 'B' -> "2"

- ...

- 'Z' -> "26"

Для декодирования закодированного сообщения все цифры должны быть сгруппированы и затем отображены обратно в буквы с использованием обратного соответствия (существует несколько способов). На예제, "11106" можно представить как:

- "AAJF" с группировкой (1 1 10 6)

- "KJF" с группировкой (11 10 6)

Обратите внимание, что группировка (1 11 06) недопустима, потому что "06" не может быть преобразовано в 'F', так как "6" отличается от "06".

Для данной строки s, содержащей только цифры, return количество способов декодирования.

Тестовые случаи сформированы таким образом, что ответ укладывается в 32-битное 정수.

예제:

Input: s = "12"

Output: 2

Explanation: "12" could be decoded as "AB" (1 2) or "L" (12).

C# 해법

매칭됨/원본
public class Solution {
    private bool valid(string s, int start, int length) {
        return length == 1 ||
               (s[start] != '0' &&
                (length < 3 || int.Parse(s.Substring(start, length)) <= 255));
    }
    private void helper(string s, int startIndex, List<int> dots,
                        List<string> ans) {
        var remainingLength = s.Length - startIndex;
        var remainingNumberOfIntegers = 4 - dots.Count;
        if (remainingLength > remainingNumberOfIntegers * 3 ||
            remainingLength < remainingNumberOfIntegers)
            return;
        if (dots.Count == 3) {
            if (valid(s, startIndex, remainingLength)) {
                var temp = "";
                var last = 0;
                foreach (var dot in dots) {
                    temp += s.Substring(last, dot) + ".";
                    last += dot;
                }
                temp += s.Substring(startIndex);
                ans.Add(temp);
            }
            return;
        }
        for (int curPos = 1; curPos <= 3 && curPos <= remainingLength;
             ++curPos) {
            dots.Add(curPos);
            if (valid(s, startIndex, curPos)) {
                helper(s, startIndex + curPos, dots, ans);
            }
            dots.RemoveAt(dots.Count - 1);
        }
    }
    public IList<string> RestoreIpAddresses(string s) {
        var ans = new List<string>();
        helper(s, 0, new List<int>(), ans);
        return ans;
    }
}

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:
    private bool valid(string s, int start, int length) {
        return length == 1 ||
               (s[start] != '0' &&
                (length < 3 || int.Parse(s.Substring(start, length)) <= 255));
    }
    private void helper(string s, int startIndex, List<int> dots,
                        List<string> ans) {
        var remainingLength = s.size() - startIndex;
        var remainingNumberOfIntegers = 4 - dots.size();
        if (remainingLength > remainingNumberOfIntegers * 3 ||
            remainingLength < remainingNumberOfIntegers)
            return;
        if (dots.size() == 3) {
            if (valid(s, startIndex, remainingLength)) {
                var temp = "";
                var last = 0;
                foreach (var dot in dots) {
                    temp += s.Substring(last, dot) + ".";
                    last += dot;
                }
                temp += s.Substring(startIndex);
                ans.push_back(temp);
            }
            return;
        }
        for (int curPos = 1; curPos <= 3 && curPos <= remainingLength;
             ++curPos) {
            dots.push_back(curPos);
            if (valid(s, startIndex, curPos)) {
                helper(s, startIndex + curPos, dots, ans);
            }
            dots.RemoveAt(dots.size() - 1);
        }
    }
    public vector<string> RestoreIpAddresses(string s) {
        var ans = new List<string>();
        helper(s, 0, new List<int>(), ans);
        return ans;
    }
}

Java 해법

매칭됨/원본
class Solution {
    private boolean valid(String s, int start, int length) {
        return (
            length == 1 ||
            (s.charAt(start) != '0' &&
                (length < 3 ||
                    s.substring(start, start + length).compareTo("255") <= 0))
        );
    }

    private void helper(
        String s,
        int startIndex,
        List<Integer> dots,
        List<String> ans
    ) {
        final int remainingLength = s.length() - startIndex;
        final int remainingNumberOfIntegers = 4 - dots.size();
        if (
            remainingLength > remainingNumberOfIntegers * 3 ||
            remainingLength < remainingNumberOfIntegers
        ) {
            return;
        }
        if (dots.size() == 3) {
            if (valid(s, startIndex, remainingLength)) {
                StringBuilder sb = new StringBuilder();
                int last = 0;
                for (Integer dot : dots) {
                    sb.append(s.substring(last, last + dot));
                    last += dot;
                    sb.append('.');
                }
                sb.append(s.substring(startIndex));
                ans.add(sb.toString());

JavaScript 해법

매칭됨/원본
var restoreIpAddresses = function (s) {
    var ans = [];
    function valid(s, start, length) {
        return (
            length == 1 ||
            (s.charAt(start) != "0" &&
                (length < 3 || s.substring(start, start + length) <= 255))
        );
    }
    function helper(s, startIndex, dots, ans) {
        var remainingLength = s.length - startIndex;
        var remainingNumberOfIntegers = 4 - dots.length;
        if (
            remainingLength > remainingNumberOfIntegers * 3 ||
            remainingLength < remainingNumberOfIntegers
        ) {
            return;
        }
        if (dots.length == 3) {
            if (valid(s, startIndex, remainingLength)) {
                var temp = "";
                var last = 0;
                for (var dot of dots) {
                    temp += s.substring(last, last + dot) + ".";
                    last += dot;
                }
                temp += s.substring(startIndex);
                ans.push(temp);
            }
            return;
        }
        for (
            var curPos = 1;
            curPos <= 3 && curPos <= remainingLength;
            ++curPos
        ) {
            dots.push(curPos);
            if (valid(s, startIndex, curPos)) {
                helper(s, startIndex + curPos, dots, ans);
            }
            dots.pop();
        }
    }
    helper(s, 0, [], ans);
    return ans;
};

Python 해법

매칭됨/원본
class Solution(object):
    def valid(self, s, start, length):
        return length == 1 or (
            s[start] != "0"
            and (length < 3 or s[start : start + length] <= "255")
        )

    def helper(self, s, startIndex, dots, ans):
        remainingLength = len(s) - startIndex
        remainingNumberOfIntegers = 4 - len(dots)
        if (
            remainingLength > remainingNumberOfIntegers * 3
            or remainingLength < remainingNumberOfIntegers
        ):
            return
        if len(dots) == 3:
            if self.valid(s, startIndex, remainingLength):
                temp = ""
                last = 0
                for dot in dots:
                    temp += s[last : last + dot] + "."
                    last += dot
                temp += s[startIndex:]
                ans.append(temp)
            return
        for curPos in range(1, min(4, remainingLength + 1)):
            dots.append(curPos)
            if self.valid(s, startIndex, curPos):
                self.helper(s, startIndex + curPos, dots, ans)
            dots.pop()

    def restoreIpAddresses(self, s):
        answer = []
        self.helper(s, 0, [], answer)
        return answer

Go 해법

매칭됨/원본
func restoreIpAddresses(s string) []string {
    var ans []string
    var valid func(s string, start int, length int) bool
    valid = func(s string, start int, length int) bool {
        return length == 1 ||
            (s[start] != '0' && (length < 3 || s[start:start+length] <= "255"))
    }
    var helper func(s string, startIndex int, dots []int)
    helper = func(s string, startIndex int, dots []int) {
        remainingLength := len(s) - startIndex
        remainingNumberOfIntegers := 4 - len(dots)
        if remainingLength > remainingNumberOfIntegers*3 ||
            remainingLength < remainingNumberOfIntegers {
            return
        }
        if len(dots) == 3 {
            if valid(s, startIndex, remainingLength) {
                temp := ""
                last := 0
                for i := 0; i < len(dots); i++ {
                    temp += s[last : last+dots[i]]
                    if last != startIndex {
                        temp += "."
                    }
                    last += dots[i]
                }
                temp += s[startIndex:]
                ans = append(ans, temp)
            }
            return
        }
        for curPos := 1; curPos <= 3 && curPos <= remainingLength; curPos++ {
            dots = append(dots, curPos)
            if valid(s, startIndex, curPos) {
                helper(s, startIndex+curPos, dots)
            }
            dots = dots[:len(dots)-1]
        }
    }
    helper(s, 0, []int{})
    return ans
}

Algorithm

1️⃣

입력им в рекурсию с данной строкой, начиная с индекса 0.

2️⃣

Для окончательного случая рекурсии мы проверяем конец строки. Если мы достигли конца строки, возвращаем 1. Каждый раз, когда мы 입력им в рекурсию, это для подстроки исходной строки. Если первый символ в подстроке равен 0, то прекращаем этот путь, возвращая 0. Таким образом, этот путь не будет влиять на количество способов.

3️⃣

Мемоизация помогает снизить Complexity, которая иначе была бы экспоненциальной. Мы проверяем словарь memo, чтобы увидеть, существует ли уже результат для данной подстроки. Если результат уже находится в memo, мы возвращаем этот результат. В противном случае количество способов для данной строки определяется путем рекурсивного вызова функции с индексом +1 для следующей подстроки и индексом +2 после проверки на валидность двузначного декодирования. Результат также сохраняется в memo с ключом как текущий индекс, чтобы сохранить его для будущих пересекающихся подзадач.

😎

Vacancies for this task

활성 채용 with overlapping task tags are 표시됨.

전체 채용
아직 활성 채용이 없습니다.