目录
还在剑指扫盲中...
难度中等292
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入:x = 2.00000, n = 10 输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3 输出:9.26100
示例 3:
输入:x = 2.00000, n = -2 输出:0.25000 解释:2-2 = 1/22 = 1/4 = 0.25
提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104
这道题可以用递归实现求幂,把对x求n次方化为求n/2、n/4次方...直到n=0时x的0次方为1,这样时间复杂度就是O(logn),空间复杂度也是O(logn)。(递归函数调用会使用栈空间)递归过程中注意当n为奇数时要多乘一个x。
class Solution {
public:
double traversal(double x, int n){
if(n == 0){
return 1.0;
}
double temp = traversal(x,n / 2);
return n % 2 ? x * temp * temp : temp * temp;//直接用traversal(...)超时
}
double myPow(double x, int n) {
return n >= 0 ? traversal(x,n) : traversal(1.0 / x,n);
}
};
2.剑指 Offer 30. 包含min函数的栈
难度简单331
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.min(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.min(); --> 返回 -2.
提示:
- 各函数的调用总次数不超过 20000 次
定义一个栈用来正常的出入栈,另一个栈用于存放当前的最小值以便用O(1)复杂度获取,每次入栈元素小于最小栈栈顶才压入最小栈,每次出栈时如果是最小值要弹出最小栈。
class MinStack {
private:
stack<int> stk;//用来正常出入
stack<int> minStk;//存放最小值
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
stk.push(x);
if(minStk.empty()){
minStk.push(x);
}
else if(x <= minStk.top()){
minStk.push(x);
}
}
void pop() {
if(!stk.empty() && !minStk.empty()){
if(minStk.top() == stk.top()){
minStk.pop();
}
stk.pop();
}
}
int top() {
return stk.top();
}
int min() {
return minStk.top();
}
};
3. 946. 验证栈序列
难度中等238
给定 pushed
和 popped
两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true
;否则,返回 false
。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1] 输出:true 解释:我们可以按以下顺序执行: push(1), push(2), push(3), push(4), pop() -> 4, push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例 2:
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2] 输出:false 解释:1 不能在 2 之前弹出。
提示:
1 <= pushed.length <= 1000
0 <= pushed[i] <= 1000
pushed
的所有元素 互不相同popped.length == pushed.length
popped
是pushed
的一个排列
题意相当于pushed经过一系列出入栈操作能否变成popped。因此定义一个栈来模拟pushed的出入,从pushed第一个元素开始入栈,如果栈顶元素等于popped当前的元素则出栈,再比较新的栈顶元素和popped的下一个元素【注意不是if】,直到栈顶和popped当前的元素不相等,此时再把pushed的下一个元素压入栈。当pushed所有元素都已经入栈后,如果栈为空,说明pushed可以经过出入栈变成popped。
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
stack<int> stk;
int pushedId = 0, popedId = 0;
for(;pushedId < pushed.size();pushedId++){
stk.push(pushed[pushedId]);
while(!stk.empty() && popped[popedId] == stk.top()){
stk.pop();
popedId++;
}
}
if(stk.empty()){
return true;
}
return false;
}
};
4. 剑指 Offer 32 - I. 从上到下打印二叉树
难度中等191
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
返回:
[3,9,20,15,7]
提示:
节点总数 <= 1000
用队列实现层序遍历,重拳出击吧:
class Solution {
public:
vector<int> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<int> ret;
if(root == nullptr){
return {};
}
que.push(root);
while(!que.empty()){
int len = que.size();
for(int i = 0; i < len; i++){
TreeNode* cur = que.front();
ret.push_back(cur -> val);
que.pop();
if(cur -> left){
que.push(cur -> left);
}
if(cur -> right){
que.push(cur -> right);
}
}
}
return ret;
}
};
5. 剑指 Offer 38. 字符串的排列
难度中等544
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]
限制:
1 <= s 的长度 <= 8
典型的回溯题目,注意s包含重复字符,要在树层进行去重:
class Solution {
public:
string temp;
vector<string> ret;
void backTrack(string& s,vector<bool>& used){
if(temp.size() == s.size()){
ret.push_back(temp);
return;
}
for(int i = 0; i < s.size(); i++){
if(i > 0 && s[i] == s[i - 1] && used[i - 1] == true){
continue;
}
if(used[i] == false){//某个字符被重复使用
used[i] = true;
temp.push_back(s[i]);
backTrack(s,used);
temp.pop_back();
used[i] = false;
}
}
}
vector<string> permutation(string s) {
vector<bool> used(s.size(),false);
sort(s.begin(),s.end());
backTrack(s,used);
return ret;
}
};