leetcode-Tencent各事业部常考题-腾讯音乐

309 阅读4分钟

来源:CodeTop

腾讯音乐

142. 环形链表 II

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow=head;//用快慢指针来解答
        ListNode *fast=head;
        while(fast)
        {
            if(!fast->next) return NULL;//如果快指针到尾还没有解决问题,无环,返回NULL
            if(fast->next) fast=fast->next->next;//如果快指针还能前进,继续
            slow=slow->next;//slow指针移动
            if(slow==fast)//当出现了环的入口,进入
            {//此时只是在环的某个位置相遇,并不是环的入口,还需要查找
                ListNode *p=head;//用数学逻辑判断
                while(p!=slow)
                {//从头部向前走,加slow继续移动,可以同时移动到环的如果
                    slow=slow->next;
                    p=p->next;
                }
                return slow;//返回环的入口
            }
        }
        return NULL;    
    }
};

468. 验证IP地址

class Solution {
public:
    string validIPAddress(string queryIP) {
        //先判断:或者.
        int flag1=0,flag2=0;
        for(int i=0;i<queryIP.length();i++)
        {
            if(queryIP[i]=='.') flag1++;
            if(queryIP[i]==':') flag2++;
        }
        if(flag1==3&&flag2==0)//如果是IPv4
        {
            int points=0;
            int left=0;int right=0;
            while(points<4)
            {
                string temp="";
                while(right<queryIP.length()&&queryIP[right]!='.')
                {
                    if(queryIP[right]>'9'||queryIP[right]<'0') return "Neither";//判断有没有不是数字的
                    temp+=queryIP[right];//加起来后续对数字大小进行判断
                    right++;//移动
                }
                if(queryIP[left]=='0'&&right-left!=1||right-left>3||right-left==0) return "Neither";//如果存在开头为0,且不是单数||过长||过短
                if(atoi(temp.c_str())>255) return "Neither"; //数字过大⭐
                left=right+1;right++;points++;//移动
            }
            return "IPv4";       
        }   
        if(flag2==7&&flag1==0)
        {
            int points=0;
            int left=0;int right=0;
            while(points<8)
            {
                while(right<queryIP.length()&&queryIP[right]!=':')
                {
                    if(queryIP[right]<='Z'&&queryIP[right]>'F'||queryIP[right]>'f'&&queryIP[right]<'z') return "Neither";//超出十六进制
                    right++;//移动
                }
                if(right-left>4||right-left==0) return "Neither";//过长或过短
                left=right+1;right++;points++;
            }
            return "IPv6";       
        }  
        return "Neither"; 
    }
};

208. 实现 Trie (前缀树)

不会,问到就摆烂

743. 网络延迟时间

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int n, int k) {
        //------------------------------------------------------
        map<int,map<int,int>> adj;//涉及到走来走去的,存图//注意写法❤
        for(auto &time :times)//先将题目给的数据存起来
        {//重点一:构件图的方法⭐
            int from=time[0];int to=time[1];int cost_time=time[2];
            adj[from][to]=cost_time;//转化为一张图,用map存,得到用时节点图
        }
        //------------------------------------------------------
        //重点二:记录visited和使用的时间,set+vector⭐
        set<int>visited;//确定访问了几个节点,用set自动去重排序
        vector<int> use_time(n+1,INT_MAX);//记录到达每个节点消耗的时间,注意只有1-n,不是0-n
        visited.insert(k);//访问点加入起点
        use_time[k]=0;//记录起点用时为0
        //------------------------------------------------------
        //重点三:用队列模仿层序遍历走完整个图
        queue<int>q;//约等于层序遍历
        q.push(k);// 将起点打入
        while(!q.empty())
        {
            int from=q.front();q.pop();visited.insert(from);//将队列投存储下来,推出,并且记为访问过的
            for(auto &[to,cost_time]:adj[from])//注意写法❤
            {//这个for就是从队列起点能到达的所有点都要更新
                int time=use_time[from]+cost_time;//到达这个点花费的时间等于源头加消耗
                if(use_time[to]>time)//取较小的时间且同时再更新一次图,如果本身是较小的时间就不更新图
                {
                    use_time[to]=time;
                    q.push(to);
                }
            }

        }
        //------------------------------------------------------
        if(visited.size()==n) return *max_element(use_time.begin()+1,use_time.end());//注意写法❤
        return -1;
        /*
        if(visited.size()==n)
        {
            int max=0;
            for(int i=1;i<use_time.size();i++)
            {
                if(use_time[i]>max) max=use_time[i];
            }
            return max;
        }
        return -1;
        */
    }
};

23. 合并K个排序链表

/**
 * 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* merge2Lists(ListNode* l1,ListNode* l2)
    {//简单的将两个有序链表合并的是实现
        if(!l1) return l2;
        if(!l2) return l1;
        ListNode *startl1=l1;
        ListNode *startl2=l2;
        ListNode *fakehead=new ListNode(-1);
        ListNode *head=fakehead;
        while(startl1&&startl2)
        {
            if(startl1->val<=startl2->val)
            {
                head->next=startl1;
                head=head->next;
                startl1=startl1->next;      
            }
            else 
            {
                head->next=startl2;
                head=head->next;
                startl2=startl2->next;
            }
        }
        if(startl1) head->next=startl1;
        if(startl2) head->next=startl2;
        return fakehead->next;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size()==0) return {};//如果为空,返回空
        if(lists.size()==1) return lists[0];//如果只有一个链表,直接返回
        if(lists.size()==2) return merge2Lists(lists[0],lists[1]);//如果是两个链表,直接返回
        //以下处理多个链表的情况
        int l=0;int r=lists.size()-1;
        while(l<r)
        {//从两头开始混合
            if(lists[l]&&lists[r])
            {//如果都不为空,开始合并
                lists[l]=merge2Lists(lists[l],lists[r]);
                r--;//l不动,右边动
            }
            if(!lists[l]) l++;//如果开头l为空移动,到不为空的地方固定
            if(!lists[r]) r--;//右边为空就移动到不为空的地方
        }
        return lists[l];//返回固定处的lists[l],合并过后的结果
    }
};

206. 反转链表

/**
 * 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 *curr=head;
        ListNode *p=nullptr;
        while(curr)
        {
            ListNode *temp=curr->next;
            curr->next=p;
            p=curr;
            curr=temp;
        }
        return p;
    }
};

378. 有序矩阵中第K小的元素


解法一:

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        vector<int> res;
        for(int i=0;i<matrix.size();i++)
        {
            for(int j=0;j<matrix.size();j++)
            {
                res.push_back(matrix[i][j]);
            }
        }
        sort(res.begin(),res.end());
        return res[k-1];
    }
};

解法二:(不理解right为什么取mid)

class Solution {
public:
    int binary(vector<vector<int>> &matrix,int mid)
    {
        int i=matrix.size()-1;
        int j=0;
        int num=0;
        while(i>=0&&j<matrix.size())
        {
            if(matrix[i][j]<=mid)
            {
                num+=i+1;
                j++;//按竖着的形式计算小于mid的个数
            }
            else i--;
        }
        return num;
    }
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int l=matrix[0][0];
        int r=matrix[matrix.size()-1][matrix.size()-1];
        while(l<r)
        {
            int mid=l+(r-l)/2; 
            if(binary(matrix,mid)>=k) r=mid;//大于k,证明这个数字取得太大了,因此需要调整右端              
            else l=mid+1;
        }
        return r;//此处返回l或者r其实都是一样的,因为最终l=r
    }
};

21. 合并两个有序链表

/**
 * 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* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode *fakeHead=new ListNode(-1);
        ListNode *head=fakeHead;
        while(list1&&list2)
        {
            if(list1->val<=list2->val)
            {
                head->next=list1;
                head=head->next;
                list1=list1->next;
            }
            else
            {
                head->next=list2;
                head=head->next;
                list2=list2->next;                
            }
        }
        if(list1) head->next=list1;
        if(list2) head->next=list2;
        return fakeHead->next;
    }
};

补充题21. 字符串相减

class Solution {
public:
    string addStrings(string num1, string num2) {
        //处理方法,倒位相加
        int i=num1.length()-1;
        int j=num2.length()-1;
        string ans="";//存储答案
        int add=0;//进位
        while(i>=0||j>=0||add!=0)//ij分别处理当短了的情况,add处理当加完了数字,但是仍然存在进位的情况
        {
            int n1,n2;

            if(i<0) n1=0;
            else n1=num1[i]-'0';
            i--;//如果数字位用完,用0填补,如果不是取出数字,i--

            if(j<0) n2=0;
            else n2=num2[j]-'0';
            j--;//如果数字位用完,用0填补,如果不是取出数字,j--

            int result=add+n1+n2;//处理该位数字和进位
            ans+=('0'+result%10);
            add=result/10;//注意进位
        }
        reverse(ans.begin(),ans.end());//翻转
        return ans;//返回答案
    }
};