CMU硕士101-妙用数据结构

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,前缀和积分图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值