实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
分析:用一个栈来存放 ‘(’ 外计算得到的数值,一个栈用于存放 ‘(’ 外的运算符。如果遇到 ‘)’,就更新一下括号内外表达式的运算结果。
class Solution {
public:
int calculate(string s) {
stack nums, ops;
long num = 0;
int res = 0;
int op = 1;
for (char c : s) {
if (isdigit(c)) {
num = num * 10 + c - '0';
}
else {
res += op * num;
num = 0;
if (c == '+') op = 1;
else if (c == '-') op = -1;
else if (c == '(') {
nums.push(res);
ops.push(op);
res = 0;
op = 1;
}
else if (c == ')' && ops.size()) {
res = ops.top() * res + nums.top();
ops.pop();
nums.pop();
}
}
}
res += op * num;
return res;
}
};
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。
class Solution {
public:
int calculate(string s) {
long res = 0, num = 0, n = s.size();
char op = '+';
stack st;
for (int i = 0; i < n; ++i)
{
if (isdigit(s[i]))
{
num = num * 10 + s[i] - '0';
}
if ((s[i] < '0' && s[i] != ' ') || i == n - 1)
{
if (op == '+') st.push(num);
if (op == '-') st.push(-num);
if (op == '*' || op == '/')
{
int tmp = (op == '*') ? st.top() * num : st.top() / num;
st.pop();
st.push(tmp);
}
op = s[i];
num = 0;
}
}
while (!st.empty()) {
res += st.top();
st.pop();
}
return res;
}
};
加减乘除以及小括号
class Solution {
public:
int calculate(string s) {
long res = 0, curRes = 0, num = 0, n = s.size();
char op = '+';
for (int i = 0; i < n; ++i) {
char c = s[i];
if (c >= '0' && c <= '9') {
num = num * 10 + c - '0';
}
if (c == '+' || c == '-' || c == '*' || c == '/' || i == n - 1) {
switch (op) {
case '+': curRes += num; break;
case '-': curRes -= num; break;
case '*': curRes *= num; break;
case '/': curRes /= num; break;
}
if (c == '+' || c == '-' || i == n - 1) {
res += curRes;
curRes = 0;
}
op = c;
num = 0;
}
}
return res;
}
};
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
遍历字符串,找到出现次数少于k次的字符,位置记为i,分为(0,i-1) 和(i+1, s.size() - 1)两个区间,再递归,最后取两区间的最大值。
int longestSubstring(string s, int k)
{
if (!s.size()) return 0;
int *hashMap = new int[26];
for (int i = 0; i < 26; i++)
hashMap[i] = 0;
for (int i = 0; i < s.size(); i++) //hashmap[i]表示字符i出现的次数
hashMap[s[i] - 'a']++;
int sum = 0;
bool flag = false; //记录是否有小于k次的字符
for (int i = 0; i < s.size(); i++)
{
if (hashMap[s[i] - 'a'] < k)
{
flag = true;
sum = max(longestSubstring(s.substr(0, i), k), longestSubstring(s.substr(i + 1, s.size()), k));
//这里直接break 如果不break 不影响结果 但影响效率 会重复计算相同的情况
break;
}
}
if (!flag)
return s.size();
return sum;
}
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
class MedianFinder {
priority_queuemax; //从大到小排序
priority_queue,greater >min; //从小到大排序
public:
MedianFinder() {
}
void addNum(int num) {
max.push(num);
min.push(max.top());
max.pop();
if(max.size()
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
分析:题目要求我们代码的时间复杂度为 O(n),提示我们要用双向队列deque来解题,并提示我们窗口中只留下有用的值,没用的全移除掉。大概思路是用双向队列保存数字的下标,遍历整个数组,如果此时队列的首元素是 i-k 的话,表示此时窗口向右移了一步,则移除队首元素。然后比较队尾元素和将要进来的值,如果小的话就都移除,然后此时我们把队首元素加入结果中即可,参见代码如下:
class Solution {
public:
vector maxSlidingWindow(vector& nums, int k)
{
vector res;
deque q;
for (int i = 0; i < nums.size(); ++i)
{
if (!q.empty() && q.front() == i - k) q.pop_front();
while (!q.empty() && nums[q.back()] < nums[i]) q.pop_back();
q.push_back(i);
if (i >= k - 1) res.push_back(nums[q.front()]);
}
return res;
}
};
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
分析:直接用sort()排序肯定是最简单的方法,但是确不是本题真正想考察的东西,可以说有一定的偷懒嫌疑。
用小跟堆做复杂度是O(n),先把数组的前k个元素push到优先队列里面,再循环剩下的元素,如果元素比队头元素(优先队列里面最小的元素)还要小,continue,否则,删除队头元素,把该元素push到队列里面,这样,循环结束后队头元素就是这k个元素里面最小的元素,即第k个最大元素。
class Solution {
public:
int findKthLargest(vector& nums, int k) {
priority_queue,greater >q(nums.begin(),nums.begin()+k);
int i=k;
for(;iq.top())
{
q.pop();
q.push(nums[i]);
}
}
return q.top();
}
};
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。
分析:我们使用一个最大堆,然后遍历数组每一个元素,将其加入堆,根据最大堆的性质,大的元素会排到最前面,然后我们看当前堆中的元素个数是否大于k,大于的话就将首元素去掉,循环结束后我们返回堆中的首元素即为所求。
class Solution {
public:
int kthSmallest(vector>& matrix, int k) {
priority_queueq;
for(int i=0;ik)q.pop();
}
}
return q.top();
}
};
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
class Solution {
public:
vector topKFrequent(vector& nums, int k) {
mapm;
priority_queue >q;
vectorans;
for(auto a:nums)
m[a]++;
for(auto it:m)
q.push({it.second,it.first});
for(int i=0;i
补充题目:
Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.
方法一:一目了然,可以用暴力求解,但是时间复杂度肯定是O(n2)
class Solution {
public:
int subarraySum(vector& nums, int k) {
int count = 0;
int n=nums.size();
for (int start = 0; start < n; start++) {
int sum=0;
for (int end = start; end < n; end++) {
sum+=nums[end];
if (sum == k)
count++;
}
}
return count;
}
};
方法二:可以利用
hashmap
记录和的累加值来避免重复计算
时间复杂度和空间复杂度都是O(n)
class Solution {
public:
int subarraySum(vector& nums, int k) {
mapm;
m[0]=1;
int res=0;
int sum=0;
for(int i=0,len=nums.size();i