17 打印从 1 到最大的 n 位数
输入数字 n
,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明:
- 用返回一个整数列表来代替打印
- n 为正整数
题解
class Solution {
public:
vector<int> printNumbers(int n) {
int max=pow(10,n)-1;
vector<int> res;
for(int i=1;i<=max;i++){
res.push_back(i);
}
return res;
}
};
/*若考虑大数则应换dfs全排列做法*/
19(10) 正则表达式匹配
请实现一个函数用来匹配包含'. '
和'*'
的正则表达式。模式中的字符'.'
表示任意一个字符,而'*'
表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"
与模式"a.a"
和"ab*ac*a"
匹配,但与"aa.a"
和"ab*a"
均不匹配。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母以及字符.
和*
,无连续的'*'
。
题解
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size() + 1, n = p.size() + 1;
vector<vector<bool>> dp(m, vector<bool>(n, false));
dp[0][0] = true;
// 初始化首行
for(int j = 2; j < n; j += 2)
dp[0][j] = dp[0][j - 2] && p[j - 1] == '*';
// 状态转移
for(int i = 1; i < m; i++) {
for(int j = 1; j < n; j++) {
if(p[j - 1] == '*') {
if(dp[i][j - 2]) dp[i][j] = true; // 1.
else if(dp[i - 1][j] && s[i - 1] == p[j - 2]) dp[i][j] = true; // 2.
else if(dp[i - 1][j] && p[j - 2] == '.') dp[i][j] = true; // 3.
} else {
if(dp[i - 1][j - 1] && s[i - 1] == p[j - 1]) dp[i][j] = true; // 1.
else if(dp[i - 1][j - 1] && p[j - 1] == '.') dp[i][j] = true; // 2.
}
}
}
return dp[m - 1][n - 1];
}
};
/*当 p[j - 1] != '*' 时, dp[i][j] 在当以下任一情况为 true 时等于 true :
dp[i - 1][j - 1] 且 s[i - 1] = p[j - 1]:字符串 s 的前 i-1 个字符和 p 的前 j -1个字符匹配, 且s的第i个字符等于p的第j个字符;
dp[i - 1][j - 1] 且 p[j - 1] = '.': 字符串 s 的前 i-1 个字符和 p 的前 j -1个字符匹配, 且p的第j个字符为'.';
*/
来源:作者:Krahets
链接:https://leetcode.cn/problems/zheng-ze-biao-da-shi-pi-pei-lcof/solutions/494128/jian-zhi-offer-19-zheng-ze-biao-da-shi-pi-pei-dong/
20 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
- 若干空格
- 一个 小数 或者 整数
- (可选)一个
'e'
或'E'
,后面跟着一个 整数 - 若干空格
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'
或'-'
) 下述格式之一:
- 至少一位数字,后面跟着一个点
'.'
- 至少一位数字,后面跟着一个点
'.'
,后面再跟着至少一位数字 - 一个点
'.'
,后面跟着至少一位数字
- 至少一位数字,后面跟着一个点
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'
或'-'
) - 至少一位数字
部分数值列举如下:
["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]
部分非数值列举如下:
["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
示例 1:
输入:s = "0"
输出:true
示例 2:
输入:s = "e"
输出:false
示例 3:
输入:s = "."
输出:false
示例 4:
输入:s = " .1 "
输出:true
提示:
1 <= s.length <= 20
s
仅含英文字母(大写和小写),数字(0-9
),加号'+'
,减号'-'
,空格' '
或者点'.'
题解
class Solution {
public:
enum State {
STATE_INITIAL,
STATE_INT_SIGN,
STATE_INTEGER,
STATE_POINT,
STATE_POINT_WITHOUT_INT,
STATE_FRACTION,
STATE_EXP,
STATE_EXP_SIGN,
STATE_EXP_NUMBER,
STATE_END
};
enum CharType {
CHAR_NUMBER,
CHAR_EXP,
CHAR_POINT,
CHAR_SIGN,
CHAR_SPACE,
CHAR_ILLEGAL
};
CharType toCharType(char ch) {
if (ch >= '0' && ch <= '9') {
return CHAR_NUMBER;
} else if (ch == 'e' || ch == 'E') {
return CHAR_EXP;
} else if (ch == '.') {
return CHAR_POINT;
} else if (ch == '+' || ch == '-') {
return CHAR_SIGN;
} else if (ch == ' ') {
return CHAR_SPACE;
} else {
return CHAR_ILLEGAL;
}
}
bool isNumber(string s) {
unordered_map<State, unordered_map<CharType, State>> transfer{
{
STATE_INITIAL, {
{CHAR_SPACE, STATE_INITIAL},
{CHAR_NUMBER, STATE_INTEGER},
{CHAR_POINT, STATE_POINT_WITHOUT_INT},
{CHAR_SIGN, STATE_INT_SIGN}
}
}, {
STATE_INT_SIGN, {
{CHAR_NUMBER, STATE_INTEGER},
{CHAR_POINT, STATE_POINT_WITHOUT_INT}
}
}, {
STATE_INTEGER, {
{CHAR_NUMBER, STATE_INTEGER},
{CHAR_EXP, STATE_EXP},
{CHAR_POINT, STATE_POINT},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_POINT, {
{CHAR_NUMBER, STATE_FRACTION},
{CHAR_EXP, STATE_EXP},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_POINT_WITHOUT_INT, {
{CHAR_NUMBER, STATE_FRACTION}
}
}, {
STATE_FRACTION,
{
{CHAR_NUMBER, STATE_FRACTION},
{CHAR_EXP, STATE_EXP},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_EXP,
{
{CHAR_NUMBER, STATE_EXP_NUMBER},
{CHAR_SIGN, STATE_EXP_SIGN}
}
}, {
STATE_EXP_SIGN, {
{CHAR_NUMBER, STATE_EXP_NUMBER}
}
}, {
STATE_EXP_NUMBER, {
{CHAR_NUMBER, STATE_EXP_NUMBER},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_END, {
{CHAR_SPACE, STATE_END}
}
}
};
int len = s.length();
State st = STATE_INITIAL;
for (int i = 0; i < len; i++) {
CharType typ = toCharType(s[i]);
if (transfer[st].find(typ) == transfer[st].end()) {
return false;
} else {
st = transfer[st][typ];
}
}
return st == STATE_INTEGER || st == STATE_POINT || st == STATE_FRACTION || st == STATE_EXP_NUMBER || st == STATE_END;
}
};
44(400) 数字序列中的某一位数字
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
示例 1:
输入:n = 3
输出:3
示例 2:
输入:n = 11
输出:0
限制:
0 <= n < 2^31
题解
int digit = 1;//数位
long start = 1;//开始数字
long count = 9;
while(n>count){
n -= count;
digit += 1;
start *= 10;
count = digit*start*9;
}
long num = start + (n-1)/digit;//第二步
return to_string(num)[(n-1)%digit]-'0';
46 把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:
0 <= num < 2^31
题解
class Solution {
public:
int translateNum(int num) {
string str = to_string(num);
int len=str.size();
string tmp="";
vector<int> dp(len+1,0);
dp[0]=1;
dp[1]=1;
for(int i=2;i<=len;i++){
tmp=str.substr(i-2,2);
dp[i]=(tmp<="25" && tmp >= "10")? dp[i-1]+dp[i-2]:dp[i-1];
}
return dp[len];
}
};
M59 - II 队列的最大值
请定义一个队列并实现函数 max_value
得到队列里的最大值,要求函数max_value
、push_back
和 pop_front
的均摊时间复杂度都是O(1)。
若队列为空,pop_front
和 max_value
需要返回 -1
示例 1:
输入:
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出: [null,null,null,2,1,2]
示例 2:
输入:
["MaxQueue","pop_front","max_value"]
[[],[],[]]
输出: [null,-1,-1]
限制:
1 <= push_back,pop_front,max_value的总操作数 <= 10000
1 <= value <= 10^5
题解
class MaxQueue {
queue<int> que;
deque<int> deq;
public:
MaxQueue() { }
int max_value() {
return deq.empty() ? -1:deq.front();
}
void push_back(int value) {
que.push(value);
while(!deq.empty() && deq.back()<value)
deq.pop_back();
deq.push_back(value);
}
int pop_front() {
if(que.empty()) return -1;
int val = que.front();
if(val==deq.front())
deq.pop_front();
que.pop();
return val;
}
};
/**
* Your MaxQueue object will be instantiated and called as such:
* MaxQueue* obj = new MaxQueue();
* int param_1 = obj->max_value();
* obj->push_back(value);
* int param_3 = obj->pop_front();
*/
M61 扑克牌顺子
从若干副扑克牌中随机抽 5
张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
示例 1:
输入: [1,2,3,4,5]
输出: True
示例 2:
输入: [0,0,1,2,5]
输出: True
限制:
数组长度为 5
数组的数取值为 [0, 13] .
题解
class Solution {
public:
bool isStraight(vector<int>& nums) {
// int max=-1;
// int min=14;//[0,13]正常取值范围
// int joker=0;
// for(int num: nums)
// {
// if(num==0){joker++;continue;}
// if(num>max){max=num;continue;}
// if(num<min){min=num;continue;}
// }
// if(joker==0)
// {
// if(max-min<5)return true;
// else return false;
// }
// else if(max-min<=5)
// {
// return true;
// }
// else return false;
set<int> s;
for(int i:nums){
if(s.find(i)!=s.end())return 0;
if(i)s.insert(i);
}
return *s.rbegin()-*s.begin()<5;
}
};
64 求 1+2+3+...+n
求 1+2+...+n
,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例 1:
输入: n = 3
输出: 6
示例 2:
输入: n = 9
输出: 45
限制:
1 <= n <= 10000
题解
/*使用递归和短路判断终止递归*/
class Solution {
public:
int res=0;
int sumNums(int n) {
bool x = n > 1 && sumNums(n-1) > 0;
res += n;
return res;
}
};
65 不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
示例:
输入: a = 1, b = 1
输出: 2
提示:
a
,b
均可能是负数或 0- 结果不会溢出 32 位整数
题解
class Solution {
public:
int add(int a, int b) {
//因为不允许用+号,所以求出异或部分和进位部分依然不能用+ 号,所以只能循环到没有进位为止
while(b!=0)
{
//保存进位值,下次循环用
int c=(unsigned int)(a&b)<<1;//C++中负数不支持左移位,因为结果是不定的
//保存不进位值,下次循环用,
a^=b;
//如果还有进位,再循环,如果没有,则直接输出没有进位部分即可。
b=c;
}
return a;
}
};
M67(8) 把字符串转换成整数
写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: "42"
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
题解
class Solution {
public:
int strToInt(string str) {
bool sign = true;
int i=0;
while(i<str.size() && str[i]==' ')i++;
if(str[i]=='-'){
sign = false;
i++;
}
else if(str[i]=='+')i++;
if(str[i]<'0' || str[i]>'9')return 0;
int res=0;
int num;
int border=__INT_MAX__/10;
while(i<str.size()){
if(str[i]<'0'||str[i]>'9')break;
if(res>border||res==border&&str[i]>'7')
return sign==true?__INT_MAX__:INT_MIN;
num=str[i]-'0';
res=res*10+num;
i++;
}
return sign==true?res:-res;
}
};