算法重启(五)

数组:

        1、给定一个长度为 n 的数组,其中包含范围为 1 到 n 的整数,有些整数重复了多次,有些整数 没有出现,求 1 到 n 中没有出现过的整数。

        

vector<int> findDisappearedNumbers(vector<int>&nums){
    vector<int>ans;
    for(const int &num:nums){
        int pos=abs(num)-1;
        if(nums[pos]>0){
            nums[pos]=-nums[pos] ;
        }
    }
    for(int i=0;i<nums.size();i++){
        if(nums[i]>0){
            ans.push_back(i+1);
        }
       }
    return ans;
}
            

        2、给定一个 n × n 的矩阵,求它顺时针旋转 90 度的结果,且必须在原矩阵上修改(in-place)。 怎样能够尽量不创建额外储存空间呢?

        

void rotate(vector<vector<int>>& matrix) {
    int temp = 0, n = matrix.size()-1;
    for (int i = 0; i <= n / 2; ++i) {
        for (int j = i; j < n - i; ++j) {
            temp = matrix[j][n-i];
            matrix[j][n-i] = matrix[i][j];
            matrix[i][j] = matrix[n-j][i];
            matrix[n-j][i] = matrix[n-i][n-j];
            matrix[n-i][n-j] = temp;
            }
        }
}

3、给定一个二维矩阵,已知每行和每列都是增序的,尝试设计一个快速搜索一个数字是否在矩 阵中存在的算法。

bool searchMatrix(vector<vector<int>>& matrix,int target){
    int m=matrix.size();
    if(m==0) return false;
    int n=matrix[0].size();
    int i=0,j=n-1;
    while(i<m&&j>=0){
        if(matrix[i][j]==target){
            return true;
        }
        if(matrix[i][j]>target){
            --j;
        }
        else{
                ++i;
        }
    }
    return false;
}

4、给定一个含有 0 到 n 整数的数组,每个整数只出现一次,求这个数组最多可以分割成多少个 子数组,使得对每个子数组进行增序排序后,原数组也是增序的。

void maxChunksToSorted(vector<int>&arr){
    int chunks=0,cur_max=0;
    for(int i=0;i<arr.size();i++){
        cur_max=max(cur_max,arr[i]);
        if(cur_max==i){
            ++chunks;
        }
    }
    return chunks;
}

栈和队列:

       1、尝试使用栈(stack)来实现队列(queue)。 

        

Class MyQueue{
    stack<int> in,out;
public:
    MyQueue(){}
    void push(int x){
        in.push(x);
    }
    int pop (){
        in2out();
        int x=out.top();
        out.pop();
        return x;
    }
    int peek(){
        in2out();
        return out.top();
    }
    
    void in2out(){    
        if(out.empty()){
            while(!in.emppty()){
                int x=in.top();
                in.pop();
                out.push(x);
            }
        }
    {

    bool empty(){
        return in.empty()&&out.empty();
    }
};

2、设计一个最小栈,除了需要支持常规栈的操作外,还需要支持在 O(1) 时间内查询栈内最小 值的功能。

Class MinStack{
    stack<int> s,min_s;
public:
    MinStack(){}
    
    void push(int x){
        s.push(x);
        if(min_s.empty()||min_s.top()<=x){
            min_s.push(x);
        }
    }
        
    void pop(){
        if(!min_s.empty()&& min_s.top()==s.top()){
            min_s.pop();
        }
        s.pop();
    }

    int top(){
            return s.top();
        }

    int getMin(){
        return min_s.top();
    }
}

3、给定一个只由左右原括号、花括号和方括号组成的字符串,求这个字符串是否合法。合法的 定义是每一个类型的左括号都有一个右括号一一对应,且括号内的字符串也满足此要求。

bool isValid(String s){
    stack<char> parsed;
    for (int i = 0; i < s.length(); ++i) {
        if (s[i] == ’{’ || s[i] == ’[’ || s[i] == ’(’) {
            parsed.push(s[i]);
        } else {
            if (parsed.empty()) {
                return false;
            }
        char c = parsed.top();
        if((s[i]=='}'&& c == '{'||(s[i] == ’]’ && c == ’[’) ||(s[i] == ’)’ && c == ’(’)){
            parsed.pop();
        else{
            return false;}
        }
    }
    }
    return parseed.empty();
}

单调栈

1、给定每天的温度,求对于每一天需要等几天才可以等到更暖和的一天。如果该天之后不存在 更暖和的天气,则记为 0。

vector<int>dailyTamperatures(vector<int>&temperatures){
    int n=temperatures.size();
    vector<int> ans(n);
    stack<int> indices;
    for(int i=0;i<n;++i){
        while(!indices.empty()){
            int pre_index=indices.top();
            if(temoeratures[i]<=temperatures[pre_index]){
                break;
            }
            indices.pop();
            ans[pre_inddex]=i-pre_index;
       }
        indices.push(i);
    }
    return ans;
}

优先队列

        优先队列可以在O(1)时间内获得最大值,并且可以在O(logn)时间内取出最大值或插入任意值。

        优先队列通常用堆来实现。堆是一个完全二叉树,其每个节点的值总是大于等于子节点的值。实现堆时,我们通常用一个数组而不是指针建立一个树,这是因为堆时完全二叉树,所以用数组表示时,位置i的节点的父节点位置一定为i/2,而它的两个子节点的位置又一定分别为2i和2i+1.

1、实现一个优先队列:

vector<int> heap;
void top(){
    return heap[0];
}

void push(int k){
    heap.push_back(k);
    swim(heap.size()-1);
}

void pop(){
    heap[0]=heap.back();
    head.pop_back();
    sink(0);
}

void swim(int pos){
    while (pos > 1 && heap[pos/2] < heap[pos])) {
        swap(heap[pos/2], heap[pos]);
        pos /= 2;
}

void sink(int pos) {
    while (2 * pos <= N) {
        int i = 2 * pos;
        if (i < N && heap[i] < heap[i+1]) ++i;
        if (heap[pos] >= heap[i]) break;
            swap(heap[pos], heap[i]);
            pos = i;
                }
        }
    
    

2、给定 k 个增序的链表,试将它们合并成一条增序链表。

struct Comp{
    bool operator()(ListNode*l1,ListNode*l2){
        return l1-val > l2-> val;
    }
    
ListNode* merageKLists(vector<ListNode*>& lists){
    if(lists.empty()) return nullptr;
    priortiy_queue<ListNode*,vector<ListNode*>,Comp>q;
    for(ListNode* list:lists){
        if(list){
            q.push(list);
        }
    }
ListNode* dummy =new ListNode(0) ,*cur=dummy;
while(!q.empty()){
    cuur->next=q.top();
    q.pop();
    cur=cur->next;
    if(cur->next){
        q.push(cur->next)
        }
    }
    return dummy->next;
}
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值