面试刷题记录

1、排序

在这里插入图片描述

  • 快速排序

void qsort(vector<int> &arr,int l,int r){
    
    
    if(l>r) return;
    int tmp=arr[l];
    int i=l,j=r;
    while(i<j){
    
    
        while(arr[j]>=tmp && j>i) j--;
        while(arr[i]<=tmp && j>i) i++;
        if(j>i) swap(arr[i],arr[j]);
    }
    arr[l]=arr[i];
    arr[i]=tmp;
    qsort(arr,l,i-1);
    qsort(arr,i+1,r);
}
  • 快排思想找第K大/第K小

class Solution {
    
    
public:
    int ans=0;
    void qsort(vector<int> &arr,int l,int r,int k){
    
    
        if(l>r) return ;
        int tmp=arr[l];
        int i=l,j=r;
        while(i<j){
    
    
            while(arr[j]>=tmp && j>i) j--;
            while(arr[i]<=tmp && j>i) i++;
            if(j>i) swap(arr[i],arr[j]);
        }
        arr[l]=arr[i];
        arr[i]=tmp;
        if(i==k){
    
    
            ans=arr[i];
            return;
        }
        else if(i>k) qsort(arr,l,i-1,k);
        else qsort(arr,i+1,r,k);
    }
    int findKth(vector<int> a, int n, int K) {
    
    
        qsort(a,0,n-1,n-K);//第K大
        //qsort(arr,0,n-1,K);//第K小
        return ans;
    }
};
  • 归并排序

int b[1000007];
void mergesort(vector<int> &arr,int l,int r){
    
    
    if(l>=r) return;
    int mid=(l+r)>>1;
    mergesort(arr,l,mid);
    mergesort(arr,mid+1,r);
    int i=l,j=mid+1,len=l;
    while(i<=mid && j<=r){
    
    
        while(arr[i]<=arr[j] && i<=mid) b[len++]=arr[i],i++;
        b[len++]=arr[j],j++;
    }
    while(i<=mid) b[len++]=arr[i],i++;
    while(j<=r) b[len++]=arr[j],j++;
    for(int i=l;i<=r;i++) arr[i]=b[i];
}
  • 冒泡排序

void bsort(vector<int> &arr){
    
    
    int n=(int) arr.size();
    for(int i=0;i<n;i++)
        for(int j=0;j<n-i-1;j++)
            if(arr[j]>arr[j+1]) swap(arr[j],arr[j+1]);
}

2、树

  • 已知前序和中序遍历,还原二叉树

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
public:
    vector<int> p,v;
    TreeNode* rebuild(int pl,int pr,int vl,int vr){
    
    
        if(pl>pr) return NULL;
        TreeNode* rt=new TreeNode(p[pl]);
        for(int i=vl;i<=vr;i++) if(v[i]==rt->val){
    
    
            rt->left=rebuild(pl+1,pl+i-vl,vl,i-1);
            rt->right=rebuild(pl+i-vl+1,pr,i+1,vr);
            break;
        }
        return rt;
    }
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
    
    
        for(auto x:pre) p.push_back(x);
        for(auto x:vin) v.push_back(x);
        int n=(int)p.size();
        return rebuild(0,n-1,0,n-1);
    }
};
  • 判断二叉树是否对称(递归)

class Solution {
    
    
public:
    bool flag=true;
    bool check(TreeNode *l,TreeNode *r){
    
    
        if(!flag) return false;
        if(l==NULL && r==NULL) return true;
        if((l==NULL)^(r==NULL)) return flag=false;
        if(l->val != r->val) return flag=false;
        return (check(l->left,r->right)&&check(l->right,r->left));
    }
    bool isSymmetric(TreeNode* root) {
    
    
        if(root==NULL) return true;
        return check(root->left,root->right);
    }
};
  • 二叉树的层次遍历

vector<vector<int> > levelOrder(TreeNode* root) {
    
    
    queue<TreeNode*> Q[2];
    vector<vector<int> > ans;
    if(root==NULL) return ans;
    int op=0;
    Q[0].push(root);
    while(true){
    
    
        vector<int> V;
        while(!Q[op].empty()){
    
    
            TreeNode* cur=Q[op].front();
            Q[op].pop();
            V.push_back(cur->val);
            if(cur->left!=NULL) Q[op^1].push(cur->left);
            if(cur->right!=NULL) Q[op^1].push(cur->right);
        }
        if(V.size()==0) break;
        ans.push_back(V);
        op^=1;
    }
    return ans;
}
  • 二叉树中的最大路径和

class Solution {
    
    
public:
    int ans=0;
    int dfs(TreeNode* rt){
    
    
        int a=0,b=0;
        if(rt->left!=NULL) a=max(0,dfs(rt->left));
        if(rt->right!=NULL) b=max(0,dfs(rt->right));
        ans=max(a+b+rt->val,ans);
        return rt->val+max(a,b);
    }
    int maxPathSum(TreeNode* root) {
    
    
        ans=root->val;
        dfs(root);
        return ans;
    }
};
  • 求二叉搜索树第k小

/*
二叉搜索树:左子树内一定都小于根,右子树内一定都大于根
思想:先数左子树,不够k个再数右子树
*/
class Solution {
    
    
public:
    int ans=-1,num=0;
    void check(TreeNode *rt,int k){
    
    
        if(rt==NULL || ans!=-1) return;
        check(rt->left,k);
        num++;
        if(num==k) ans=rt->val;
        else check(rt->right,k);
    }
    int kthSmallest(TreeNode* root, int k) {
    
    
        check(root,k);
        return ans;
    }
};

3、链表

  • 反转链表

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
    
    
public:
    ListNode* ReverseList(ListNode* pHead) {
    
    
        ListNode *pre=NULL;
        ListNode *cur=pHead;
        ListNode *nxt=NULL;
        while(cur){
    
    
            nxt=cur->next;
            cur->next=pre;
            pre=cur;
            cur=nxt;
        } 
        return pre;
    }
};
  • 判断链表中是否有环(快慢指针)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    bool hasCycle(ListNode *head) {
    
    
        ListNode *a=head;
        ListNode *b=head;
        while(a!=NULL && a->next!=NULL){
    
    
            a=a->next->next;
            b=b->next;
            if(a==b) return true;
        }
        return false;
    }
};
  • 合并链表(辅助头指针)

class Solution {
    
    
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    
    
        ListNode *ans= new ListNode(0);
        ListNode *l=ans;
        while(l1!=NULL && l2!=NULL){
    
    
            if(l1->val < l2->val){
    
    
                l->next=l1;
                l1=l1->next;
            }
            else{
    
    
                l->next=l2;
                l2=l2->next;
            }
            l=l->next;
        }
        l->next=(l1==NULL)?l2:l1;
        return ans->next;
    }
};
  • 每k个一组翻转链表(栈)

class Solution {
    
    
public:
    ListNode* reverseKGroup(ListNode *head, int k) {
    
    
        ListNode *ans=new ListNode(0);
        ListNode *res=ans;
        ListNode *p=head;
        stack<ListNode*> S;
        while(true){
    
    
            int len=0;
            ListNode *pre=p;
            while(len<k && p!=NULL){
    
    
                S.push(p);
                len++;
                p=p->next;
            }
            if(len<k){
    
    
                res->next=pre;
                break;
            }
            while(!S.empty()){
    
    
                res->next=S.top();
                S.pop();
                res=res->next;
            }
        }
        return ans->next;
    }
};
  • 链表中环的入口(快慢指针)

class Solution {
    
    
public:
    ListNode *detectCycle(ListNode *head) {
    
    
        ListNode *slow=head;
        ListNode *fast=head;
        while(fast!=NULL && fast->next!=NULL){
    
    
            slow=slow->next;
            fast=fast->next->next;
            if(slow==fast){
    
    
                ListNode *pre=head;
                while(pre!=slow){
    
    
                    pre=pre->next;
                    slow=slow->next;
                }
                return pre;
            }
        } 
        return NULL;
    }
};
  • 有序链表去重(双指针)

ListNode* deleteDuplicates(ListNode* head) {
    
    
    if(head==NULL) return NULL;
    ListNode *a=head,*b=head;
    while(a!=NULL){
    
    
        if(a->val != b->val){
    
    
            b->next=a;
            b=a;
        }
        a=a->next;
    }
    b->next=NULL;
    return head;
}
  • 设计LRU缓存(List+unordered_map)

//设计LRUcache类
#include<unordered_map>
class LRUCache {
    
    
public:
    struct node{
    
    int key,val;};
    list<node> L;
    unordered_map<int,list<node>::iterator> mp;
    int lim=0;
    LRUCache(int k) {
    
    
        lim=k;
    }
    void check(){
    
    
        if(L.size()<=lim) return;
        auto it=L.end();--it;
        mp.erase((*it).key);
        L.erase(it);
    }
    void put(int key,int val){
    
    
        auto it=mp.find(key);
        if(it!=mp.end()){
    
    
            L.erase(it->second);
            mp.erase(key);
        } 
        L.push_front({
    
    key,val});
        mp[key]=L.begin();
        check();
    }
    int get(int key){
    
    
        auto it=mp.find(key);
        if(it==mp.end()) return -1;
        int val=(it->second)->val;
        L.erase(it->second);
        mp.erase(key);
        L.push_front({
    
    key,val});
        mp[key]=L.begin();
        check();
        return val;
    }
};
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
const int mod=1e9+7;
const ll INF=1e18;
struct node{
    
    int key,val;};
class Solution {
    
    
public:
    list<node> L;
    unordered_map<int,list<node>::iterator> mp;
    int lim=0;
    void check(){
    
    
        if(L.size()<=lim) return;
        auto it=L.end();--it;
        mp.erase((*it).key);
        L.erase(it);
    }
    void Set(int key,int val){
    
    
        auto it=mp.find(key);
        if(it!=mp.end()){
    
    
            L.erase(it->second);
            mp.erase(key);
        } 
        L.push_front({
    
    key,val});
        mp[key]=L.begin();
        check();
    }
    int Get(int key){
    
    
        auto it=mp.find(key);
        if(it==mp.end()) return -1;
        int val=(it->second)->val;
        L.erase(it->second);
        mp.erase(key);
        L.push_front({
    
    key,val});
        mp[key]=L.begin();
        check();
        return val;
    }
    vector<int> LRU(vector<vector<int> > a, int k) {
    
    
        lim=k;
        vector<int> ans;
        for(auto x:a){
    
    
            if(x[0]==1) Set(x[1],x[2]);
            else ans.pb(Get(x[1]));
        }
        return ans;
    }
}st;
void rua(){
    
    
    int n,k;scanf("%d%d",&n,&k);
    vector< vector<int> > a;
    a.resize(n);
    for(int i=0;i<n;i++){
    
    
        int op,x;scanf("%d%d",&op,&x);
        a[i].pb(op);a[i].pb(x);
        if(op==1){
    
    
            scanf("%d",&x);a[i].pb(x);
        }
    }
    vector<int> ans=st.LRU(a,k);
    for(auto x:ans) printf("%d ",x);puts("");
    return;
}
int main(){
    
    
    rua();
    return 0;
}
  • 合并k个有序链表

class Solution {
    
    
public:
    ListNode *merge(ListNode *a,ListNode *b){
    
    
        if(a==NULL) return b;
        if(b==NULL) return a;
        if(a->val < b->val){
    
    
            a->next=merge(a->next,b);
            return a;
        }
        else{
    
    
            b->next=merge(a,b->next);
            return b;
        }
    }
    ListNode *mergeKLists(vector<ListNode *> &lists) {
    
    
        if(lists.size()==0) return NULL;
        ListNode *ans=NULL;
        for(auto x:lists) ans=merge(ans,x);
        return ans;
    }
};

4、二分

  • 寻找两个升序数组的中位数

/*
思想:查找两个数组中的第k小
通过比较a[k/2-1]和b[k/2-1],排除掉a或b的前一部分,从而缩小k的范围至1或某一数组被全部排除
注意分类讨论和边界条件
*/
class Solution {
    
    
public:
    double check(const vector<int>& a,const vector<int>& b,int k) {
    
    
        int posa=0,posb=0;
        int n=(int)a.size(),m=(int)b.size();
        while(1){
    
    
            if(posa>=n) return 1.0*b[posb+k-1];
            if(posb>=m) return 1.0*a[posa+k-1];
            if(k==1) return 1.0*min(a[posa],b[posb]);
            int p=k/2-1;
            int sa=min(posa+p,n-1);
            int sb=min(posb+p,m-1);
            if(a[sa]<=b[sb]) k-=(sa-posa+1),posa=sa+1;
            else k-=(sb-posb+1),posb=sb+1;
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    
    
        int n=(int)nums1.size(),m=(int)nums2.size();
        double res=check(nums1,nums2,(m+n)/2+1);
        if((m+n)&1) return res;
        else return (check(nums1,nums2,(m+n)/2)+res)/2.0;
    }
};

5、字符串

  • 按顺序输出一个字符集构成的所有串( D F S DFS DFS

class Solution {
    
    
public:
    set<string> S;
    void check(int pos,string s){
    
    
        if(pos==s.length()){
    
    
            S.insert(s);
            return;
        }
        for(int i=pos;i<s.length();i++){
    
    
            swap(s[pos],s[i]);
            check(pos+1,s);
            swap(s[pos],s[i]);
        }
    }
    vector<string> Permutation(string str) {
    
    
        if(str.length()==0) return {
    
    };
        check(0,str);
        return vector<string>({
    
    S.begin(),S.end()});
    }
};
  • 按顺序输出一个字符集构成的所有串(非递归)

class Solution {
    
    
public:
    template<typename Iterator>
    bool my_next_permutation(Iterator l,Iterator r){
    
    
        if(l == r) return false;
        Iterator i=r;
        if(l == --i) return false;
        while(1){
    
    
            Iterator i1=i,i2;
            if(*(--i) < *i1){
    
    
                i2=r;
                while(*i >= *(--i2));
                iter_swap(i,i2);
                reverse(i1,r);
                return true;
            }
            if(i == l){
    
    
                reverse(l,r);
                return false;
            }
        }
    }
    vector<string> Permutation(string str) {
    
    
        vector<string> ans;
        sort(str.begin(),str.end());
        do{
    
    
            ans.push_back(str);
        }while(my_next_permutation(str.begin(),str.end()));
        return ans;
    }
};

6、其他

  • 矩阵快速幂(斐波那契)

class Solution {
    
    
public:
    int f[1000007];
    struct matrix{
    
    
        int a[2][2];
        matrix() {
    
    memset(a,0,sizeof(a));}
    };
    matrix mul(matrix s1,matrix s2){
    
    
        matrix c;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                for(int k=0;k<2;k++)
                    c.a[i][j]+=s1.a[i][k]*s2.a[k][j];
        return c;
    }
    int qpow(int n){
    
    
        if(n==-1) return 0;
        matrix base,res;
        base.a[0][0]=base.a[1][0]=base.a[0][1]=1;
        res.a[0][0]=res.a[1][1]=1;
        while(n){
    
    
            if(n&1) res=mul(res,base);
            base=mul(base,base);
            n>>=1;
        }
        return res.a[0][0];
    }
    int Fibonacci(int n){
    
    
        return qpow(n-1);
    }
};
  • n l o g n nlogn nlogn求最长上升子序列

/*
dp[i]表示长度为i的最长上升子序列结尾的最小值
dp[i]一定是递增的,所以可以通过二分更新dp
*/
int lengthOfLIS(vector<int>& nums) {
    
    
    int n=(int)nums.size();
    std::vector<int> dp(n+1);
    int len=0;dp[++len]=nums[0];
    for(int i=1;i<n;i++){
    
    
        if(nums[i]>dp[len]) dp[++len]=nums[i];
        else{
    
    
            int l=1,r=len,res=0;
            while(l<=r){
    
    
                int mid=(l+r)>>1;
                if(dp[mid]<nums[i]) l=mid+1,res=mid;
                else r=mid-1;
            }
            dp[res+1]=nums[i];
        }
    }
    return len;
}
  • n l o g n nlogn nlogn求字典序最小的最长上升子序列

/*
a[i]记录第i个数在LIS中的最早位置
然后倒序扫一遍,按len到1倒着找到这个序列
arr 3 2 1 4 3 5 1
a   1 1 1 2 2 3 1
于是找到 1 3 5
*/
vector<int> LIS(vector<int>& arr) {
    
    
    int n=(int)arr.size(),len=0;
    vector<int> f(n+1),a(n+1);
    f[++len]=arr[0];a[0]=1;
    for(int i=1;i<n;i++){
    
    
        if(arr[i]>f[len]) f[++len]=arr[i],a[i]=len;
        else{
    
    
            int l=1,r=len,res=0;
            while(l<=r){
    
    
                int mid=(l+r)>>1;
                if(f[mid]<arr[i]) l=mid+1,res=mid;
                else r=mid-1;
            }
            f[res+1]=arr[i];
            a[i]=res+1;
        }
    }
    vector<int> ans(len);
    for(int i=n-1,j=len;i>=0;i--){
    
    
        cout<<i<<' '<<a[i]<<endl;
        if(a[i]==j){
    
    
            ans[j-1]=arr[i];
            j--;
        }
        if(j==0) break;
    }
    return ans;
}

猜你喜欢

转载自blog.csdn.net/qq_43813163/article/details/113485967