leetcode-Tencent各事业部常考题-IEG

362 阅读4分钟

来源:CodeTop 待补充

补充题4. 手撕快速排序

class Solution {
public:
    void quickSort(int left,int right,vector<int> &nums)
    {
        if(left>=right) return;
        int i=left;
        int j=right;
        int pivot=rand()%(right-left+1)+left;//要用差值来rand,比如递归的右边不是从0开始计数的⭐
        swap(nums[pivot],nums[left]);//取随机一个数,每次都取最左边的超时
        int base=nums[left];
        while(i<j)
        {
            while(nums[j]>=base&&i<j) j--;//⭐
            while(nums[i]<=base&&i<j) i++;//⭐
            swap(nums[i],nums[j]);   
        }
        swap(nums[i],nums[left]);
        quickSort(left,i-1,nums);
        quickSort(i+1,right,nums);
    }
    vector<int> sortArray(vector<int>& nums) {
        quickSort(0,nums.size()-1,nums);
        return nums;
    }
};

补充知识:

  1. 图解快速排序(C++实现)_Magnum的博客-CSDN博客_c++快速排序
  2. C++中rand()函数的用法_风暴计划-CSDN博客_c++ rand()

704. 二分查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l=0;
        int r=nums.size()-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(nums[mid]==target) return mid;
            else if(nums[mid]<target) l=mid+1;
            else if(nums[mid]>target) r=mid-1;
        }
        return -1;
    }
};

160. 相交链表

使用set

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        set<ListNode*>res;
        ListNode *temp=headA;
        while(temp)
        {
            res.insert(temp);
            temp=temp->next;
        }
        temp=headB;
        while(temp)
        {
            if(res.count(temp)) return temp;
            else temp=temp->next;
        }
        return NULL;
    }
};

双指针法:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(!headA||!headB) return nullptr;
        ListNode *A=headA;
        ListNode *B=headB;
        while(A!=B)
        {
            if(A==nullptr) A=headB;
            else A=A->next;

            if(B==nullptr) B=headA;
            else B=B->next;
        }
        return A;
    }
};

232. 用栈实现队列

class MyQueue {
public:
    stack<int> instack;//先产生两个栈
    stack<int> outstack;
    void in2out(stack<int> &instack,stack<int> &outstack)
    {//两个栈的输入
        if(outstack.empty())
        {
            while(!instack.empty())
            {
                outstack.push(instack.top());
                instack.pop();                
            }
        }
    }
    MyQueue() {}
    
    void push(int x) 
    {//推入到接收的栈
        instack.push(x);
    }
    
    int pop() 
    {//弹出输出的栈
        if(outstack.empty()) in2out(instack,outstack);
        int x=outstack.top();
        outstack.pop();
        return x;
    }
    
    int peek() {//输出top元素
        if(outstack.empty()) in2out(instack,outstack);
        return outstack.top();
    }
    
    bool empty() {//判断两个栈是不是空的
        return outstack.empty()&&instack.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

1. 两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int>res;//用一个map存储值和下标
        for(int i=0;i<nums.size();i++)
        {
            auto it=res.find(target-nums[i]);//找是否存在另一个对应的数字
            if(it!=res.end()) return {it->second,i};//如果存在,返回下标和当前搜索到的下标
            res[nums[i]]=i;//如果不存在,就存进去
        }
        return {};
    }
};

14. 最长公共前缀

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int le=strs[0].length();
        for(int i=0;i<strs.size();i++)
            le=le<strs[i].length()?le:strs[i].length();
              
        string record = strs[0].substr(0,le);
        for(int i=0;i<strs.size();i++)
            for(int j=0;j<le;j++)
                if(record[j]!=strs[i][j]) 
                    record=record.substr(0,j); //参数=起始位置+截取长度                                 
        return record;
    }
};

21. 合并两个有序链表

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;
    }
};

494. 目标和

class Solution {
public:
    int method=0;
    void dfs(vector<int> &nums,int target,int k)
    {   
        if(target==0&&k==nums.size()) //注意k要到nums.size(),因为相当于k是步数,最短为1
        {
            method++;
            return;
        }
        if(k<nums.size())dfs(nums,target-nums[k],k+1);//注意控制k的大小
        if(k<nums.size())dfs(nums,target+nums[k],k+1);//注意控制k的大小
    }
    int findTargetSumWays(vector<int>& nums, int target) {
        if(nums.size()==0) return 0;//注意处理长度为0的情况
        if(nums.size()==1) return nums[0]==target||nums[0]==-target;//处理长度为1的情况
        dfs(nums,target,0);//处理长度为2的情况
        return method;
    }
};

25. K 个一组翻转链表

补充题5. 手撕归并排序

189. 旋转数组

227. 基本计算器 II

不大聪明的解题思路

class Solution {
public:
    int calculate(string s) {
        stack<int> num;//存数字
        stack<char> sym;//存字符
        string temp;//存字符串
        for(int i=0;i<s.length();i++)
        {
            if(s[i]>='0'&&s[i]<='9')//处理数字
            {
                while(i<s.length()&&s[i]>='0'&&s[i]<='9')
                {
                    temp+=s[i];
                    i++;
                }
                num.push(atoi(temp.c_str()));
                temp="";
                i--;   //后退一步             
            }
            else if(s[i]=='+'||s[i]=='-')//+-放后面
            {
                sym.push(s[i]);
            }
            else if(s[i]=='/')//除法进行处理
            {
                int x=num.top();
                num.pop();
                while(s[i]>'9'||s[i]<'0') i++;//跳过空格
                while(i<s.length()&&s[i]>='0'&&s[i]<='9')
                {
                    temp+=s[i];
                    i++;
                }
                int y=(atoi(temp.c_str()));
                num.push(x/y);
                temp="";
                i--;                   
            }
            else if(s[i]=='*')//乘法处理
            {
                int x=num.top();
                num.pop();
                while(s[i]>'9'||s[i]<'0') i++;//跳过空格
                while(i<s.length()&&s[i]>='0'&&s[i]<='9')
                {
                    temp+=s[i];
                    i++;
                }
                int y=(atoi(temp.c_str()));
                num.push(x*y);
                temp="";
                i--;                  
            }
            else continue;
        }
        stack<int> num1;//反过来进行加减法
        stack<char> sym1;
        while(!num.empty())
        {
            num1.push(num.top());
            num.pop();
        }
        while(!sym.empty())
        {
            sym1.push(sym.top());
            sym.pop();
        }
        while(!sym1.empty())
        {
            int x=num1.top();num1.pop();
            int y=num1.top();num1.pop();
            if(sym1.top()=='+')
            {
                num1.push(x+y);
                sym1.pop();
            }
            else if(sym1.top()=='-')
            {
                num1.push(x-y);
                sym1.pop();                
            }
        }
        return num1.top();

    }
};

大聪明解法

class Solution {
public:
    int calculate(string s) {
        vector<int> nums;//用vector存比stack方便
        char sign='+';//优先设一个符号,类似于链表设一个头节点方便计算
        int num=0;//统计数字
        for(int i=0;i<s.length();i++)
        {
            if(s[i]<='9'&&s[i]>='0')//对数字进行处理
            {
                num=num*10+(s[i]-'0');
            }
            if(i==s.length()-1||s[i]>'9'||s[i]<'0'&&s[i]!=' ')//对符号进行处理
            {
                switch(sign)
                {
                    case '+': nums.push_back(num);break;//是+-先存起来
                    case '-': nums.push_back(-num);break;
                    case '*': nums[nums.size()-1]=nums[nums.size()-1]*num;break;//是乘除,优先进行处理
                    case '/': nums[nums.size()-1]=nums[nums.size()-1]/num;break;
                }
                sign=s[i];//存下一个符号
                num=0;//更新数字
            }
            if(s[i]==' ')continue;
        }
        int res=0;//计算总数值
        for(int i=0;i<nums.size();i++) res+=nums[i];
        return res;//返回总答案
    }
};

567. 字符串的排列

这道题只能说和我理解的子串不一个意思
子串:S2长度等于S1长度的子串,包含S1中的所有字符

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        vector<int> res1(26,0);
        vector<int> res2(26,0);
        if(s1.length()>s2.length()) return false;
        for(int i=0;i<s1.length();i++)
        {
            res1[s1[i]-'a']++;
            res2[s2[i]-'a']++;
        }
        if(res1==res2) return true;
        for(int i=s1.length();i<s2.length();i++)
        {
            res2[s2[i]-'a']++;
            res2[s2[i-s1.length()]-'a']--;
            if(res1==res2) return true;
        }
        return false;
    }
};

141. 环形链表

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

31. 下一个排列

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int i=nums.size()-2;//找到nums的倒数第二位 1375【4】9631
        while(i>=0&&nums[i]>=nums[i+1]) i--;//找出第一个不是按降序(从左至右)排列的数字
        if(i>=0)
        {
            int j=nums.size()-1;//1375【4】9[6]31
            while(j>=0&&nums[i]>=nums[j])j--;//找到第一个比之前找到的数字大的数字
            swap(nums[i],nums[j]);//交换这两个数字 1375【6】9[4]31
        }
        reverse(nums.begin()+i+1,nums.end());//因为之前是降序的,反过来,让这个数字不要过大 1375【6】13[4]9 i的位置不变,如果是降序的,直接就被替换成了升序的
    }
};

15. 三数之和

32. 最长有效括号

class Solution {
public:
    int longestValidParentheses(string s) {
        stack<int> st;//先写一个栈
        int ans=0;//一个存最大数量的数字
        for(int i=0,start=0;i<s.length();i++)
        {
            if(s[i]=='(') st.push(i);//如果是正常的左括号,输入到栈中
            else if(s[i]==')')//如果是右括号,进入判断程序
            {
                if(st.empty()) start=i+1;//如果整个栈是空的,证明没有匹配的左括号,更新统计起点
                else if(!st.empty())//如果栈不为空,证明有匹配的左括号
                {
                    st.pop();//先将左括号弹出
                    if(st.empty()) ans=max(ans,i-start+1);//如果完全匹配,那么用现在的 i-start+1就是最长的长度
                    else if(!st.empty()) ans =max(ans,(i-(st.top()+1)+1));//如果不完全匹配,证明匹配的是内层的左括号,内层左括号下标为st.top()+1
                    //因此ans=i-(st.top()+1)+1
                }
            }
        }
        return ans;//返回最长的长度
    }
};

剑指 Offer 45. 把数组排

622. 设计循环队列

146. LRU缓存机制

补充题4. 手撕快速排序

160. 相交链表

1. 两数之和

206. 反转链表

155. 最小栈

232. 用栈实现队列

21. 合并两个有序链表

25. K 个一组翻转链表