Mudou para um novo tema de tipografia, haha, como você se sente?
Aviso: alguns amigos gravadores disseram que muitas vezes não veem artigos diários. Agora, a conta oficial não é recomendada de acordo com o horário de envio, mas fica fora de ordem de acordo com algumas regras, então você pode ter seguido o "Código de Registro Aleatório" e nunca ter visto o artigo. Recomenda-se definir uma estrela para "Código Caprice". Após definir a estrela, ela será empurrada de acordo com a hora da postagem todos os dias. Carl envia regularmente às 8:35 todos os dias, oh pontual!
738. Números que aumentam monotonicamente
Dado um inteiro não negativo N, encontre o maior inteiro menor ou igual a N, e esse inteiro precisa satisfazer que os números em cada dígito estão aumentando monotonicamente.
(Se e somente se os números xey de cada dígito adjacente satisfizerem x <= y, chamamos esse número inteiro de aumento monotônico.)
Exemplo 1:
Entrada: N = 10
Saída: 9
Exemplo 2:
Entrada: N = 1234
Saída: 1234
Exemplo 3:
Entrada: N = 332
Saída: 299
Explicação: N é um número inteiro no intervalo de [0, 10 ^ 9].
A ideia de
uma solução violenta
é muito simples, então a primeira coisa a se pensar é uma solução violenta. Deixe-me mencionar uma onda de violência. O resultado é, naturalmente, horas extras!
código mostrado abaixo:
class Solution {
private:
bool checkNum(int num) {
int max = 10;
while (num) {
int t = num % 10;
if (max >= t) max = t;
else return false;
num = num / 10;
}
return true;
}
public:
int monotoneIncreasingDigits(int N) {
for (int i = N; i > 0; i--) {
if (checkNum(i)) return i;
}
return 0;
}
};
- Complexidade de tempo: O (n * m) m é o comprimento do número de n
- Complexidade do espaço: O (1) O problema de
algoritmo guloso
requer o maior número inteiro crescente monotonicamente menor ou igual a N, então tome um número de dois dígitos como exemplo.
Por exemplo: 98, uma vez que strNum [i-1]> strNum [i] ocorre (não aumentando monotonicamente), primeiro eu quero strNum [i-1] -, e então strNum [i] é 9 para que este número inteiro seja 89, isto é, o maior número inteiro monotonicamente crescente menor que 98.
Se você pensar sobre isso com clareza, essa questão será mais fácil de lidar.
Ótimo local: no caso de strNum [i-1]> strNum [i], deixe strNum [i-1] - e, em seguida, strNum [i] a 9 para garantir que esses dois bits se tornem o maior número inteiro monotonicamente crescente .
Ótimo global: obtenha o maior número inteiro monotonicamente crescente menor ou igual a N.
Mas aqui o ótimo local é derivado do ótimo global, e outras condições são necessárias, ou seja, a ordem de passagem e a marca a partir da qual o bit começa a ser alterado para 9.
É para atravessar da frente para trás ou de trás para a frente?
Se você atravessar da frente para trás, se strNum [i-1]> strNum [i] for encontrado, deixe strNum [i-1] subtrair um, mas se strNum [i-1] for subtraído por um, pode ser menor que strNum [i-2].
Isso é um pouco abstrato, por exemplo, o número: 332, se você percorrer da frente para trás, ele se torna 329. Nesse momento, 2 é menor que os 3 primeiros e o resultado real deve ser 299.
Portanto, percorrer da frente para trás mudará os resultados que foram percorridos!
Em seguida, percorrendo de trás para a frente, você pode reutilizar o resultado da última comparação. O valor de 332 da travessia de trás para a frente muda para: 332 -> 329 -> 299
Depois de determinar a ordem de travessia, o ótimo local pode ser apresentado ao global neste momento, e nenhum contra-exemplo pode ser encontrado, tente ser ganancioso.
O código C ++ é o seguinte:
class Solution {
public:
int monotoneIncreasingDigits(int N) {
string strNum = to_string(N);
// flag用来标记赋值9从哪里开始
// 设置为这个默认值,为了防止第二个for循环在flag没有被赋值的情况下执行
int flag = strNum.size();
for (int i = strNum.size() - 1; i > 0; i--) {
if (strNum[i - 1] > strNum[i] ) {
flag = i;
strNum[i - 1]--;
}
}
for (int i = flag; i < strNum.size(); i++) {
strNum[i] = '9';
}
return stoi(strNum);
}
};
- Complexidade de tempo: O (n) n é o comprimento do número
- Complexidade do espaço: O (n) requer uma string e é mais conveniente converter em uma operação de string.
Para resumir
esta questão, basta pensar em um exemplo claro, como 98. Assim que strNum [i-1]> strNum [i] ocorre (não aumentando monotonicamente) ), primeiro quero subtrair um de strNum [i-1] e atribuir 9 a strNum [i], de modo que o inteiro seja 89. Você pode naturalmente pensar na solução gananciosa correspondente.
Pensando na ganância, devemos também considerar a ordem de travessia.Somente percorrendo de trás para a frente os resultados da última comparação podem ser reutilizados.
Quando o código final é implementado, algumas habilidades também são necessárias, como usar uma bandeira para marcar onde começar a atribuição de 9.
Aprenda o algoritmo passo a passo e procure por "Code Random Record"!