Sexta-feira, 12 de fevereiro de 2021, o tempo está bom [Não lamente o passado, não desperdice o presente, não tema o futuro]
Conteúdo deste artigo
1. Introdução
Sword Finger Offer 67. Converta uma string em um inteiro
2. A situação é complicada, considere cuidadosamente
2.1 Uma escova (2021.2.12)
class Solution {
public:
int strToInt(string str) {
int res = 0, bndry = INT_MAX / 10;
int i = 0, sign = 1, length = str.size();
if(length == 0) return 0;
// 删除开头的空格
while(str.at(i) == ' ')
if(++i == length) return 0;
// 判断是否是负数
if(str.at(i) == '-') sign = -1;
// 跳过符号位
if(str.at(i) == '-' || str.at(i) == '+') ++i;
// 计算数值的大小
for(int j = i; j < length; j++) {
// 不是数字直接退出
if(str.at(j) < '0' || str.at(j) > '9') break;
// 巧妙判断数字是否越界
if(res > bndry || res == bndry && str.at(j) > '7')
return sign == 1 ? INT_MAX : INT_MIN;
res = res * 10 + (str.at(j) - '0');
}
return sign * res;
}
};
2.2 Segunda escova (2021.3.15)
O código do chefe foi reproduzido diretamente no primeiro pincel, e eu o escrevi novamente no segundo pincel, e encontrei um sentimento diferente, principalmente para julgar se o número está fora dos limites. O método de escrita do chefe é muito inteligente, mas não é fácil de pensar. Meu método é simples e direto, e é mais fácil inventá-lo durante uma entrevista real.
class Solution {
public:
int myAtoi(string s) {
const int n = s.size();
int i = 0, num = 0;
bool sign = true;
// 删除开头的空格
while(i<n && s[i]==' ') ++i;
if(i>=n) return 0;
// 判断是否是负数
if(s[i]=='-') sign = false;
// 跳过符号位
if(s[i]=='-' || s[i]=='+') ++i;
// 计算数值的大小
int tmp = 0;
while(i<n && isdigit(s[i])){
tmp = s[i]-'0';
// 判断数字是否越界
if(num<=(INT_MAX-tmp)/10) num = 10*num + tmp;
else break;
++i;
}
// 这里需要注意的是 if 的条件,不能用 if(num<=(INT_MAX-tmp)/10) 来判断
// 原因是 num 的值本身可能略小于 INT_MAX,就会出现 num>(INT_MAX-tmp)/10,就没法返回 num 了
if(i<n && isdigit(s[i])) return sign?INT_MAX:INT_MIN;
else return sign?num:-num;
}
};
2.3 Considere entrada inválida e estouro de inteiro
O livro "Sword Finger Offer Second Edition" considera a entrada inválida (se o número não for lido, a entrada é considerada inválida) e a situação de estouro de inteiro. Neste momento, será um pouco mais problemático e você precisará usar dois Uma variável de sinalizador global para refletir, o código também foi ligeiramente alterado.
Se a entrada é inválida pode ser confirmada após julgar o bit de sinal. O estouro de inteiro é dividido em estouro INT_MIN e estouro INT_MAX. Porque ao julgar se ele estourou, INT_MAX (2147483647) é usado, então quando A entrada de INT_MIN (-2147483648) é também considerado um estouro, situação que requer consideração
class Solution {
public:
bool isVaild = true;
bool isOverflow = false;
public:
int myAtoi(string s) {
// 默认输入是有效的,且没有溢出
isVaild = true;
isOverflow = false;
const int n = s.size();
int i = 0, num = 0;
bool sign = true;
// 删除开头的空格
while (i < n && s[i] == ' ') ++i;
// 判断是否是负数
if (i < n && s[i] == '-') sign = false;
// 跳过符号位
if (i < n && (s[i] == '-' || s[i] == '+')) ++i;
// 判断输入是否有效(如果没有读到数字,则认为输入是无效的)
if (i >= n || !isdigit(s[i])) {
isVaild = false;
return 0;
}
// 计算数值的大小
int tmp = 0;
while (i < n && isdigit(s[i])) {
tmp = s[i] - '0';
// 判断数字是否越界(因为使用的是 INT_MAX(2147483647) 来判断是否越界,所以 -2147483648 会被认为越界了)
if (num <= (INT_MAX - tmp) / 10) num = 10 * num + tmp;
else break;
++i;
}
// 这里需要注意 if 的条件,不能用 if(num<=(INT_MAX-tmp)/10) 来判断
// 原因是 num 的值本身可能略小于 INT_MAX,就会出现 num>(INT_MAX-tmp)/10,就没法返回 num 了
if (i < n && isdigit(s[i])) {
// 如果输入不是最小的整数 INT_MIN(-2147483648),说明真的越界了
if (!(sign == false && num == INT_MAX / 10 && tmp == 8)) isOverflow = true;
return sign ? INT_MAX : INT_MIN;
}
else return sign ? num : -num;
}
};
referências
"Oferta Espada Dedo Segunda Edição"
https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/solution/mian-shi-ti-67-ba-zi-fu-chuan- zhuan-huan-cheng-z-4 /