面试编程题目总结

本文详细介绍了在LeetCode上遇到的各种算法问题及其解决方案,包括链表问题、队列实现、查找最近公共祖先、三数之和、LRU缓存、字符串排列、俄罗斯套娃信封问题以及快速排序等,并提供了相应的C++代码实现。此外,还涉及到了数据库表项、视频面试流程、分布式系统设计以及多线程同步问题。
摘要由CSDN通过智能技术生成

1.leetcode中出现not all control paths return a value
参考:https://blog.csdn.net/ping_lvy/article/details/84402064
在leetcode上做题,一直提示这个,原来是因为各分支必须有返回值

题目:判断链表中是否有环

https://www.nowcoder.com/practice/650474f313294468a4ded3ce0f7898b9?tpId=188&tqId=37531&rp=1&ru=%2Factivity%2Foj&qru=%2Fta%2Fjob-code-high-week%2Fquestion-ranking&tab=answerKey

快慢指针同步移动,最后判断是否重合

/**
 * 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 *fast=head;
        ListNode *slow=head;
        while(fast!=NULL&&fast->next!=NULL){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)return true;
        }
        return false;
    }
};

用两个栈来实现一个队列

链接:https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6?tpId=188&tqId=37536&rp=1&ru=%2Factivity%2Foj&qru=%2Fta%2Fjob-code-high-week%2Fquestion-ranking&tab=answerKey

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }
    int pop() {
        if(stack2.size()==0)
        while(stack1.empty()!=1){
            stack2.push(stack1.top());
            stack1.pop();
        }
        int x=stack2.top();
        stack2.pop();
        return x;
    }
private:
    stack<int> stack1;
    stack<int> stack2;
};

寻找第K大

链接:
https://www.nowcoder.com/practice/e016ad9b7f0b45048c58a9f27ba618bf?tpId=188&tqId=37518&rp=1&ru=%2Factivity%2Foj&qru=%2Fta%2Fjob-code-high-week%2Fquestion-ranking&tab=answerKey

class Solution {
public:
    void find_kth(vector<int>& a,int left,int right,int K){//必须用&不然每次都是开辟新的,最后最外层等于没有修改
        int l=left,r=right;
        int mid=a[(l+r)/2];
        while(l<=r){
            while(a[l]<mid)l++;
            while(a[r]>mid)r--;
            if(l<=r){
                swap(a[l],a[r]);
                l++;
                r--;
            }
        }
        if(r>left&&K<=r)find_kth(a,left,r,K);
        if(l<right&&K>=l)find_kth(a,l,right,K);
    }
    int findKth(vector<int> a, int n, int K) {
        // write code here
        K--;
        find_kth(a,0,n-1,n-K-1);//注意是第k大
        return a[n-K-1];
    }
};

最大连续1的个数 III

双指针
链接:https://leetcode-cn.com/problems/max-consecutive-ones-iii/

题目大意:给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。

class Solution {
public:
    int longestOnes(vector<int>& A, int K) {
        int n=A.size();
        int l=0;
        int r=-1;
        int ans=0;
        while(r<n-1&&(A[r+1]==1||K>0)){
            r++;
            if(A[r]==0)K--;
        }
        ans=max(ans,r-l+1);
        for(int l=1;l<n;l++){
            if(l-1>r)r++;
            else if(A[l-1]==0)K++;
            while(r<n-1&&(A[r+1]==1||K>0)){
                r++;
                if(A[r]==0)K--;
            }
            ans=max(ans,r-l+1);
        }
        return ans;
    }
};

反转链表

链接:https://leetcode-cn.com/problems/reverse-linked-list/
反转一个单链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode *head) {
        ListNode *pre=NULL;
        if(head==NULL)return head;
        for(;;){
            ListNode *next=head->next;
            head->next=pre;
            if(next==NULL)break;
            pre=head;
            head=next;
        }
        return head;
    }
};

二叉树的最近公共祖先

https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/submissions/
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    map<int,TreeNode*>fa;
    map<int,bool>flag;
    void dfs(TreeNode* now){
        if(now->left!=NULL){
            fa[now->left->val]=now;
            dfs(now->left);
        }
        if(now->right!=NULL){
            fa[now->right->val]=now;
            dfs(now->right);
        }
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        fa[root->val]=NULL;
        dfs(root);
        while(p!=NULL){
            flag[p->val]=true;
            p=fa[p->val];
        }
        while(flag[q->val]==NULL)q=fa[q->val];
        return q;
    }
};

三数之和

https://leetcode-cn.com/problems/3sum/
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int>> ans;
        for(int i=0;i<n-2;i++){
            if(i>0&&nums[i]==nums[i-1])continue;
            int k=n-1;
            for(int j=i+1;j<n-1;j++){
                if(j-1>i&&nums[j]==nums[j-1])continue;
                while(k>j+1&&nums[i]+nums[j]+nums[k]>0)k--;
                if(k<=j)break;
                if(nums[i]+nums[j]+nums[k]==0){
                    ans.push_back({nums[i],nums[j],nums[k]});
                }
            }
        }
        return ans;
    }
};

LRU 缓存机制

https://leetcode-cn.com/problems/lru-cache/
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:

LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

class LRUCache {
struct node{
    int key,val;
}q[100000];
int r=0,cnt=0;
public:
    LRUCache(int capacity) {
        r=0;
        cnt=capacity;
    }
    int get(int key) {
        for(int i=1;i<=r;i++)
        if(q[i].key==key){
            node temp=q[i];
            for(int j=i;j<r;j++)q[j]=q[j+1];
            q[r]=temp;
            return temp.val;
        }
        return -1;
    }
    
    void put(int key, int value) {
        for(int i=1;i<=r;i++){
            if(q[i].key==key){
                q[i].val=value;
                node temp=q[i];
                for(int j=i;j<r;j++)q[j]=q[j+1];
                q[r]=temp;
                return;
            }
        }
        if(r<cnt){
            r++;
            q[r].key=key;
            q[r].val=value;
            return;
        }else{
            for(int i=1;i<r;i++)q[i]=q[i+1];
            q[r].key=key;
            q[r].val=value;
        }
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

字符串的排列

https://leetcode-cn.com/problems/permutation-in-string/
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
题解:直接用hash进行处理

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        int MO=1000000007;
        int len1=s1.length();
        int len2=s2.length();
        if(len1>len2)return false;
        int hash1=0,hash2=0;
        for(int i=0;i<len1;i++)hash1=(hash1+s1.charAt(i)*s1.charAt(i)*s1.charAt(i))%MO;
        for(int i=0;i<len1;i++)hash2=(hash2+s2.charAt(i)*s2.charAt(i)*s2.charAt(i))%MO;
        if(hash1==hash2)return true;
        for(int i=len1;i<len2;i++){
            hash2+=s2.charAt(i)*s2.charAt(i)*s2.charAt(i);
            hash2-=s2.charAt(i-len1)*s2.charAt(i-len1)*s2.charAt(i-len1);
            hash2=(hash2+MO)%MO;
            if(hash1==hash2)return true;
        }
        return false;
    }
}

俄罗斯套娃信封问题

https://leetcode-cn.com/problems/russian-doll-envelopes/
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

**主要是对vector数组使用了判断条件的快排**
class Solution {
    public:
    int maxEnvelopes(vector<vector<int>>& envelopes) {
        sort(envelopes.begin(),envelopes.end(),
        [](const vector<int> &a,const vector<int> &b){
            return a[0]<b[0];
        });
        int n=envelopes.size();
        int ans=0,f[110000];
        for(int i=0;i<n;i++){
            f[i]=1;
            for(int j=0;j<i;j++){
                if(envelopes[i][0]>envelopes[j][0]&&envelopes[i][1]>envelopes[j][1]){
                    f[i]=max(f[i],f[j]+1);
                }
            }
            ans=max(ans,f[i]);
        }
        return ans;
    }
};

链表快排

https://www.luogu.com.cn/problem/P1177
用链表实现快速排序

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x;
    node *next,*pre;
};
int n,x;
void kspx(node *head,node *tail,int left,int right){
    node *h=head,*t=tail;
    int l=left,r=right;
    int ra=rand()%(r-l+1);
    for(int i=1;i<=ra;i++)h=h->next;
    int mid=h->x;
    h=head;
    while(l<=r){
        while(h->x<mid)h=h->next,l++;
        while(t->x>mid)t=t->pre,r--;
        if(l<=r){
            swap(h->x,t->x);
            h=h->next;
            t=t->pre;
            l++;
            r--;
        }
    }
    if(r>left)kspx(head,t,left,r);
    if(l<right)kspx(h,tail,l,right);
}
int main(){
    cin>>n;
    node *head=new node;
    //注意不能node *head,*tail写成这样,这样会出现RunTimeError在luogu上,估计是有可能
    //head和tail没有new node,所以开成了同一个
    node *tail=new node;
    tail=head;
    for(int i=1;i<=n;i++){
        cin>>x;
        node *p=new node;
        p->x=x;
        tail->next=p;
        p->pre=tail;
        tail=tail->next;
    }
    head=head->next;
    kspx(head,tail,1,n);
    while(head!=NULL){
        cout<<head->x<<" ";
        head=head->next;
    }
    cout<<endl;
    return 0;
}

字节后端开发,视频架构 三面

m个队列,每个队列n个元素,每个队列都是单调递增的,求所有元素的前k小。

可以用个小根堆维护当前m个队列的队首,每次选出min,然后选择下一个加入堆,重复k次。复杂度klogm。

也可以用大根堆维护,当新加入的元素大于堆顶,直接放弃这个队列(因为后面的肯定不可能),如果可以,则需要退出一个(退出的那个队列之后的元素肯定也不需要了,也可以直接pass那个队列).

#include <bits/stdc++.h>
using namespace std;
struct node{
    int val,id,rank;
    bool operator <(const node &now)const{//重载运算符,以val为键值维护小根堆
        return val>now.val;
    }
};
priority_queue<node>heap;//注意一下优先队列的定义
int n,m,k,a[1110][1100];
int main(){
    cin>>m>>n;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)
            cin>>a[i][j];
    }
    for(int i=1;i<=m;i++){
        heap.push((node){a[i][1],i,1});
    }
    cin>>k;
    while(k--){
        node now=heap.top();
        heap.pop();
        cout<<now.val<<" ";
        if(now.rank<n){
            now.rank++;
            heap.push((node){a[now.id][now.rank],now.id,now.rank});//(node)直接把后面的三个元素打包成一个node型
        }

    }
    return 0;
}

介绍一下项目中的数据库表项情况

介绍一下点击双方视频面试链接进入房间的步骤,描述一下之后某方点击发起视频会话的整个过程。

我的理解是从url显示页面,之后类似游戏大厅服务器把房间激活。

知乎中搜索某一个问题,会有相关的喜好推荐,这些喜好推荐可以继续点击,不断重复这个过程。设计一个分布式的系统,可以把所有相关的内容都爬下来。

个人设计:一个队列,一个Python脚本(根据一个url得到一个所有url的集合),然后所有服务器上都放一个队列,bfs每次取出头部,然后获得一些找到的url,发给其它所有机器,注意去重,用hash,注意一下分布式的hash判重数据同步性。

三个线程依次输出1-100

待补充

hulu一面:
图片上传的逻辑
支付的过程
平时怎么学习新技术
算法题 单线程 CPU:https://leetcode-cn.com/problems/single-threaded-cpu/
vector在本地调试可以这样,vector里面是vector

#include<bits/stdc++.h>
using namespace std;
struct data{
    int dur,id;
    bool operator <(const data b)const{
        if(dur>b.dur)return 1;
        if(dur<b.dur)return 0;
        return id>b.id;
    }
};
bool taskcmp(vector<int> &a,vector<int> &b){
    return a[0]<b[0];
}
vector<int> getOrder(vector<vector<int>> task){
    int n=task.size();
    sort(task.begin(),task.end(),taskcmp);
    long long time=0;
    priority_queue<data>q;
    vector<int>res;
    int mark=0;
    for(;;){
        while(mark<n&&task[mark][0]<=time){
            q.push({task[mark][1],task[mark][2]});
            mark++;
        }
        if(q.size()>0){
            time+=q.top().dur;
            res.push_back(q.top().id);
            q.pop();
        }else{
            if(mark==n)break;
            time=task[mark][0];
        }
    }
    return res;
}
int main(){
    int n;
    cin>>n;
    vector<vector<int>> tasks;
    for(int i=0;i<n;i++){
        int st,du;
        vector<int> now;
        cin>>st>>du;
        now.push_back(st);
        now.push_back(du);
        now.push_back(i);
        tasks.push_back(now);
    }
    vector<int>ans;
    ans=getOrder(tasks);
    for(int i=0;i<ans.size();i++)cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}

或者这样 vector里面是结构体

#include<bits/stdc++.h>
using namespace std;
struct data{
    int start,duration,id;
    bool operator<(const data &b)const{
        if(duration>b.duration)return 1;
        if(duration<b.duration)return 0;
        return id>b.id;
    }
};
bool taskcmp(data a,data b){
    return a.start<b.start;
}
vector<int> getOrder(vector<data> &task){如果加&,那么里面的task实际上就是外面的tasks,里面的修改外面的也修改
    sort(task.begin(),task.end(),taskcmp);
    priority_queue<data>q;
    vector<int>res;
    long long time=0;
    int n=task.size();
    int mark=0;
    while(1){
        while(mark<n&&time>=task[mark].start){
            q.push(task[mark]);
            mark++;
        }
        if(q.size()>0){
            res.push_back(q.top().id);
            time+=q.top().duration;
            q.pop();
        }else{
            if(mark==n)break;
            time=task[mark].start;
        }
    }
    return res;
}
int main(){
    vector<data>tasks;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        int start,duration;
        cin>>start>>duration;
        tasks.push_back({start,duration,i});
    }
    vector<int>ans;
    ans=getOrder(tasks);
    for(int i=0;i<ans.size();i++)cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值