1,数组:
**448. 找到所有数组中消失的数字**
/*
一句话总结:寻找消失的数字
思路:
step1:遍历nums,如果map中不存在的, 插入
step2:遍历[1, n]。如果i在map不能找到的直接push到vector中
step3:return
注意:
*/
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int len = nums.size();
vector<int> ret;
map<int, int> map1;
for (int i = 0; i < len; i++) {
if (map1.find(nums[i]) == map1.end()) {
map1[nums[i]] = 1;
}
}
for (int i = 1; i <= len; i++) {
if (map1.find(i) == map1.end()) {
ret.push_back(i);
}
}
return ret;
}
};
48. 旋转图像
/*
一句话总结:旋转小数组
思路:
找规律, 顺时针旋转90度: ret[i][j] = matrix[j][len - 1 - i];
*/
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
vector<vector<int>> matrix_new = matrix; // 值拷贝
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
matrix_new[j][n - i - 1] = matrix[i][j];
}
}
matrix = matrix_new; // 这里也是值拷贝
}
};
240. 搜索二维矩阵 II
/*
一句话总结:快速搜索二维矩阵
思路:
从右上方开始遍历,[0, line - 1]; column = 0
while (column >=0 && line < len) {
if (target == 当前值) {
return true;
} else if (target > 当前值) {
line++;
} else {
column--;
}
return false;
}
*/
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int coulum = matrix.size();
if (coulum == 0) {
return false;
}
int line = matrix[0].size();
int columnIndex = coulum - 1;
int lineIndex = 0;
while(columnIndex >=0 && lineIndex < line) {
if (matrix[columnIndex][lineIndex] == target) {
return true;
} else if (matrix[columnIndex][lineIndex] > target) {
columnIndex --;
} else {
lineIndex++;
}
}
return false;
}
};
769. 最多能完成排序的块
/*
解题思路:考虑当前索引的位置p和1-p中最大值m的大小关系。
if(p == m) {
说明p之前的元素一定都在(1-p)范围内,可以一刀切用来保证顺序。
} else {
p之后一定有元素是小于p的,不能一刀切的
}
一刀切的依据是前pos[i,j]中,有元素[i,j],index从0开始。
*/
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
int curMax = 0, len = arr.size(), ans = 0;
for (int i = 0; i < len; i++) {
curMax = max(curMax, arr[i]);
if (curMax == i)
ans++;
}
return ans;
}
};
232. 用栈实现队列
/*
一句话理解:栈属于先进后出, 队列是先进先出
思路:用两个栈来表示队列
输入栈StaIn, 输出栈staOut
模拟push操作:
直接push到StaIn中
模拟pop操作:
if(staOut有数据) {
staOut.pop();
} else {
staIn数据逐步pop到staOut中;
最后staOut的top被pop出来.
}
模拟empty操作:
两个栈都为空方为空
获取top操作:
staIn数据逐步pop到staOut中;
最后staOut的top被pop出来.
注意:这种题目可以做一些类似
*/
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
input.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
if (out.empty()) { // 如果不是空的,获取out的第一个值,直接pop出去
while(!input.empty()) { // 如果out是空的,将input中的值逐渐pop到out中,最后取出out的top
out.push(input.top());
input.pop();
}
}
int data = out.top();
out.pop();
return data;
}
/** Get the front element. */
int peek() {
int data = this->pop();
out.push(data);
return data;
}
/** Returns whether the queue is empty. */
bool empty() {
return (input.empty() && out.empty());
}
private:
stack<int> input, out;
};
最小栈
/*
一句话理解:是一些技巧题
思路:
有两个栈,一个是接受不断的push的x,另一个是minStack,
如果push一个,发现当前的值小于等于minstack的top,将当前值push到minStack,
pop:
正常stack的pop出去,如果top的值等于minStack,将minstack也一并pop
top:
正常stack的top
minNum:
minStack中的top
延伸:
maxStack
*/
class MinStack {
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int val) {
staData.push(val);
if (minStackData.empty() || (minStackData.top() >= val)) {
minStackData.push(val);
}
}
void pop() {
int top = staData.top();
staData.pop();
if (top == minStackData.top()) {
minStackData.pop();
}
}
int top() {
return staData.top();
}
int getMin() {
return minStackData.top();
}
private:
stack<int> staData, minStackData;
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
有效的括号
/*
一句话理解:计算机+各种符号, 明显都是各种的栈操作
思路:
step1: 遍历s, 遇到那几种符号{[(就入栈,
step2:如果不是左面的几种符号,
if (栈是空) {
return false; // 因为字符串只由这几种符号构成 ,**点1**
} else {
if (sta的top和当前字符不匹配) {
return false;
} else {
pop();
}
}
if(sta不是空) { **点2**
return false;
}
return true;
注意:
①题目条件是XXX
②多注意几种情况, 点1和点2
*/
bool isValid(string s) {
int len = s.length();
stack<char> sta;
for (int i = 0; i < len; i++) {
if ((s[i] == '{') || (s[i] == '[') || (s[i] == '(')) {
sta.push(s[i]);
} else {
if(sta.empty()) {
return false;
}
if ((sta.top() == '{' && s[i] != '}') || (sta.top() == '[' && s[i] != ']') || (sta.top() == '(' && s[i] != ')')) {
return false;
}
sta.pop();
}
}
if (!sta.empty()) {
return false;
}
return true;
}
单调栈
3,单调栈
739. 每日温度
/*
求解算术表达式的结果(LeetCode 224、227、772、770)
求解直方图里最大的矩形区域(LeetCode 84)
一句话总结:单调栈, 怎样单调是针对出栈而言的, 当出栈是递增的,表示这是单调递增栈.
思路:
维持一个单调递减栈,表示每天的温度。为了方便计算天数,栈中存放的是日期,而不是温度本身。
1, 从左向右遍历温度数组,对于每个日期p,如果p的温度比栈顶存储的温度q高,说明q下一个最大数就是p,此时, pop q,记录p到q的距离。
2, 重复这一过程,直到p小于等于栈顶元素(或空栈)为止。将P入栈,然后考虑下一天。
3, 在此过程中,栈内数组永远保持单调递减,避免了使用排序进行比较。若最后栈内剩余一些数据,说明,在该数组中,他们没有下一个日期。
for(i = 0 : len) {
if(sta.empty() || arr[i] <= arr[sta.top()]) { // 这个分支是可以省略的, 因为最终都是要sta.push(i);
sta.push(i);
} else {
while(!sta.empty() && arr[i] > arr[top]) {
ret[top] = i-top;
sta.pop();
}
sta.push(i);
}
}
*/
vector<int> dailyTemperatures(vector<int>& temperatures) {
int len = temperatures.size();
stack<int> sta;
vector<int> ret (len, -1);
for (int i = 0; i < len; i++) {
if (sta.empty() || temperatures[i] <= temperatures[sta.top()]) {
sta.push(i);
} else {
while(!sta.empty() && temperatures[i] > temperatures[sta.top()]) {
ret[sta.top()] = i - sta.top();
sta.pop();
}
sta.push(i);
}
}
return ret;
}
4,优先队列
5,双端队列
6,哈希表
7,多重集合和映射
8,前缀和积分图