leetcode专项面试题解析

Leetcode-1367. 二叉树中的列表(树+递归)

/**
 * 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) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool judge(TreeNode*root, ListNode*head){
        if(head == nullptr) return true;
        if(root == nullptr) return false;
        if(root->val != head->val) return false;
        return judge(root->left,head->next) || judge(root->right,head->next);
    }
    bool isSubPath(ListNode* head, TreeNode* root) {
        if(head == nullptr) return true;
        if(root == nullptr) return false;
        //撸着比较
        if(root->val == head->val && judge(root,head)) return true;
        return isSubPath(head,root->left) || isSubPath(head,root->right);//用链表的头结点分别和树中结点进行比较
    }
};

leetcode-958. 二叉树的完全性检验
(不使用层序遍历将此题的空间复杂度降到O(1))=>(知道树节点个数之后,左子树是否含有完全二叉树要求子树结点个数,右子树同理进行递归)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
//左子树是否含有A个结点的二叉树和右子树是否含有B个结点的二叉树
    int nodeCount(TreeNode*root){
        if(root == nullptr) return 0;
        return nodeCount(root->left)+nodeCount(root->right)+1;
    }
    bool judge(TreeNode* root,int n,int m){
        if(root == nullptr) return n==0;
        if(n==0) return false;
        if(n==1) return root->left==nullptr && root->right == nullptr;
        int k = max(0,2*m-1);//k为除去最后一层的结点数量
        int l = min(m,n-k),r = n-k-l;//l为最后一层左边的结点数量,r为最后一个层右边的子树结点数量 
        return judge(root->left,(k-1)/2+l,m/2)&&judge(root->right,(k-1)/2+r,m/2);
    }
    bool isCompleteTree(TreeNode* root) {
        if(root == nullptr) return true;
        //首先知道二叉树中含有多少结点
        int n = nodeCount(root);
        int m =1;//m为倒数第二层的结点数,假设为1
        int cnt =1;//cnt为三角里面结点的数量
        while(cnt + 2*m<=n){//用于求倒数第二层m的结点数
            m*=2;
            cnt+=m;
        }
        return judge(root,n,m);//判断root树是否含有n个结点的完全二叉树

    }
};

leetcode-剑指 Offer 36. 二叉搜索树与双向链表

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    Node *head,*pre;
    void in_order(Node* root){
        if(root==nullptr)return ;
        in_order(root->left);
        //do something
        if(pre == nullptr){
            head = root;
        }else{
            pre->right = root;
        }
        root->left = pre;
        pre = root;
        in_order(root->right);
        return ;
    }
    Node* treeToDoublyList(Node* root) {
        if(root == nullptr) return head;
        head = pre = nullptr;
        in_order(root);
        head->left = pre;
        pre->right = head;
        return head;
    }
};

leetcode-464. 我能赢吗
深搜+记忆化

class Solution {
public:
    unordered_map<int,bool> h;
    bool dfs(int mask,int n,int total){
        if(h.find(mask)!=h.end()) return h[mask];
        for(int i=1;i<=n;i++){
            if(mask & (1<<i))continue;
            if(i>=total || !dfs(mask | (1<<i),n,total-i)){
                return h[mask] = true;
            }
        }
        return h[mask] = false;
    }
    bool canIWin(int maxChoosableInteger, int desiredTotal) {
        int n = maxChoosableInteger,mask = 0;//用一个整数标记哪些整数取过了
        if((1+n)*n/2<desiredTotal) return false;
        h.clear();
        return dfs(mask,maxChoosableInteger,desiredTotal);


    }
};

leetcode-172. 阶乘后的零

class Solution {
public:
    int trailingZeroes(int n) {
        int m = 5,cnt = 0;
        while(n/m){//找n里面有多少个5
            cnt += n/m;
            m*=5;
        }
        return cnt;
    }
};

leetcode-384. 打乱数组

class Solution {
public:
    vector<int> nums;
    Solution(vector<int>& nums):nums(nums){
        srand(time(0));
    }
    
    /** Resets the array to its original configuration and return it. */
    vector<int> reset() {
        return nums;
    }
    
    /** Returns a random shuffling of the array. */
    vector<int> shuffle() {
        vector<int> ret(nums);
        for(int i=0;i<ret.size();i++){
            swap(ret[i],ret[rand()%ret.size()]);
        }
        return ret;
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(nums);
 * vector<int> param_1 = obj->reset();
 * vector<int> param_2 = obj->shuffle();
 */

leetcode-437. 路径总和 III

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
unordered_map<int,int> h;//第一个int 表示出现的和值,第二个int表示出现的前缀和值多少次
    int count(TreeNode *root,int sum,int targetSum){
        if(root == nullptr) return 0;
        sum += root->val;
        int ans = h[sum-targetSum];
        h[sum] += 1;
        ans += count(root->left,sum,targetSum);
        ans +=count(root->right,sum,targetSum);
        h[sum]-=1;

        return ans;
    }
        
    int pathSum(TreeNode* root, int targetSum) {
        h.clear();
        h[0]=1;
        return count(root,0,targetSum);//中间值表示前缀和值 一开始为0
    }
};

leetcode-395. 至少有 K 个重复字符的最长子串

class Solution {
public:
    int longestSubstring(string s, int k) {
        unordered_map<char,int>cnt;
        vector<int> splits;//每一个分割点的位置(分割点由那些区间内字符数量本就不满足k个的字符组成)
        for(auto x:s) cnt[x]+=1;//统计完每种字符的数量
        for(int i=0;s[i];i++){//设定虚拟分割点的位置
            if(cnt[s[i]]<k)//如果当前字符的数量小于k次的话 说明当前字符位置就是一个分割位置
            splits.push_back(i);
        }
        splits.push_back(s.size());//最后一个虚拟分割点就放在s字符串的最后面便于最后一个区间求解
        if(splits.size() == 1) return s.size();
        int pre =0,ans=0;
        for(auto p:splits){//p表示当前分割位置
            int len = p-pre; //当前分割的长度为
            if(len>=k){//大于等于k才有求解的必要
                ans = max(ans,longestSubstring(s.substr(pre,len),k));
            }
            pre = p+1;
        }
        return ans;
    }
};

leetcode-190. 颠倒二进制位

class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
        uint32_t ret = 0;
        for(uint32_t i=0,j=1,k=(1<<31);i<32;++i,j<<=1,k>>=1){//j表示最低位k表示最高位 每次将j左移提升一位 ,k右移降低一位
            if(n & j){//如果数字n的第i位(j所对应的那个位置是1的话)就将结果位第k位置为1
                ret |= k;
            }
        }
        return ret;
    }
};

leetcode-8. 字符串转换整数 (atoi)
这道题在判断超出边界的方法上通过一个if机制就可以实现最大值和最小值的判断!!!

class Solution {
public:
    int myAtoi(string s) {
        int flag = 1,max_pre = INT_MAX/10,d = INT_MAX%10,ind=0,num=0;//ind表示当前处理到的字符串第几位,num表示转换成的数字
        while(s[ind] ==' ') ind++;
        if(s[ind] == '-'){flag = -1;ind++;}
        else if(s[ind] == '+') ind++;
        for(;s[ind];++ind){
             //如果当前字符不是一个字符
            if(s[ind]<'0'||s[ind]>'9') break;
            //判断转换的数字会越界
            if(num>max_pre || (num==max_pre && (s[ind]-'0')>d)){
                if(flag > 0) return INT_MAX;
                else return INT_MIN;
            }

            //正常(不判断越界和非法的转化)的进行字符串与数值的转换
            num = num*10+(s[ind]-'0');
        }
        return num*flag;
    }
};

leetcode-380. O(1) 时间插入、删除和获取随机元素
这题前面两个(插入和删除毫无疑问使用hash表,获取随机元素使用动态数组)

class RandomizedSet {
public:
    /** Initialize your data structure here. */
    unordered_map<int,int> h;//h值对应动态数组中的位置
    vector<int> arr;

    RandomizedSet() {
        srand(time(0));
    }
    
    /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
    bool insert(int val) {
        //如果已经有了
        if(h.find(val)!=h.end()) return false;
        //先插入到hash中然后插入到动态数组的最后一位
        h[val] = arr.size();
        arr.push_back(val);
        return true;
        
    }
    
    /** Removes a value from the set. Returns true if the set contained the specified element. */
    void swap_item(int i,int j){
        //先交换两个元素在动态数组中的位置
        swap(arr[i],arr[j]);
        //然后交换两个元素在hash表中对应的位置
        h[arr[i]] = i;
        h[arr[j]] = j;
        return ;
    }
    bool remove(int val) {
        //找到对应的值然后和动态数组的最后一位进行交换
        //首先判断值是否存在
        if(h.find(val)==h.end()) return false;
        int n=h[val],m=arr.size()-1;
        swap_item(n,m);//交换动态数组中这两个元素的位置
        h.erase(h.find(val));
        arr.pop_back();
        return true;

    }
    
    /** Get a random element from the set. */
    int getRandom() {
        return arr[rand()%arr.size()];
    }
};

/**
 * Your RandomizedSet object will be instantiated and called as such:
 * RandomizedSet* obj = new RandomizedSet();
 * bool param_1 = obj->insert(val);
 * bool param_2 = obj->remove(val);
 * int param_3 = obj->getRandom();
 */

leetcode-402. 移掉 K 位数字
这道题使用单调栈 可方便的移除k位数字 并进行讨论

class Solution {
public:
    string removeKdigits(string num, int k) {
        //本题使用单调栈
        if(k>=num.size()) return "0";
        string ret;
        for(auto x:num){
            while(k && ret.size() && ret.back()>x) ret.pop_back(),k--;
            ret.push_back(x);
        }
        //两种情况:1.k=0 2.k!=0
        //第二种说明不需要满足删除k个字符就能满足单调栈的性质(单调递增的)
        if(k!=0)ret = ret.substr(0,ret.size()-k);
        int ind = 0;
        while(ret[ind] == '0')++ind;
        ret = ret.substr(ind,ret.size());
        if(ret == "")ret="0";
        return ret;
    }
};

leetcode-1081. 不同字符的最小子序列

class Solution {
public:
    string smallestSubsequence(string s) {
        //使用单调栈
        string ret;
        unordered_map<char,int>cnt;//用于记录元素个数
        for(auto x:s)cnt[x]++;
        unordered_set<char>h;//用于记录s字符串中都有哪些字符,以便于后面在单调栈中遇到重复的字符串不再反复压入
        for(auto x:s){
            if(h.find(x)==h.end()){
                //不存在,入栈(先循环弹出不符合的元素);栈中存在不入栈
                while(ret.size() && ret.back()>x && cnt[ret.back()]) {
                    h.erase(h.find(ret.back()));
                    ret.pop_back();
                }
                h.insert(x);
                ret.push_back(x);
            }
            cnt[x]-=1;
        }
        return ret;
    }
};

leetcode-1499. 满足不等式的最大值

class Solution {
public:
//以x坐标的值为限制的滑动窗口 == 固定了j点之后,在i点找到一个yi-xi的最大值 == 维护一个单调递减队列
    int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
        deque<int> q;//记录相关点的下标
        q.push_back(0);
        int ans = INT_MIN;
        for(int i=1;i<points.size();++i){
            //首先维护一个滑动窗口,将超出边界的点都踢出去
            while(q.size() && points[i][0] - points[q.front()][0]>k) q.pop_front();
            if(q.size()){
                ans = max(ans,points[i][0]-points[q.front()][0]+points[i][1]+points[q.front()][1]);
            }
            while(q.size() && points[i][1]-points[i][0] > points[q.back()][1]-points[q.back()][0]) q.pop_back();
            q.push_back(i);
        }
        return ans;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值