2022-03-15剑指47-58

面试题47

简单dp

class Solution {
public:
    int maxValue(vector<vector<int> >& grid) {
        // write code here
        int m=grid.size();
        int n=grid[0].size();
        vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
        for(int i=1; i<=m; ++i){
            for(int j=1; j<=n; ++j){
                dp[i][j]=max(dp[i-1][j], dp[i][j-1])+grid[i-1][j-1];
            }
        }
        return dp[m][n];
    }
};

模拟方法

面试题48

注意这题,子串是连续的,和子序列不同
字串数量可以查下怎么算的,排列组合插空法。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //双指针,一个指当前判断的子串头,一个指尾
        unordered_map<char, int> m;
        int ans=0;
        int left=-1;
        for(int i=0; i<s.size(); ++i){
            if(m.find(s[i]) != m.end()){
                left=max(left, m.find(s[i])->second);
                //更新left,这个重复的字符不在里面的话就不处理,否则left换为这个重复字符的位置
            }
            m[s[i]]=i;
            ans=max(ans, i-left);
        }
        return ans;
    }
};

面试题49

题解链接

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        vector<int> dp(index+1,0);
        dp[1]=1;
        int dp2=1, dp3=1, dp5=1;
        int a=1, b=1, c=1;
        for(int i=2; i<=index; ++i){
            dp2=dp[a]*2;
            dp3=dp[b]*3;
            dp5=dp[c]*5;
            dp[i]=min(min(dp2, dp3), dp5);
            if(dp[i]==dp2) ++a;
            if(dp[i]==dp3) ++b;
            if(dp[i]==dp5) ++c;
        }
        return dp[index];
    }
};

面试题50

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        unordered_map<char, int> m;
        for(char c:str){
            m[c]++;
        }
        for(int i=0; i<str.size(); ++i){
            if(m[str[i]]==1) return i;
        }
        return -1;
    }
};

面试题51

这题牛客要模1000000007,代码中两个注释掉的%1000000007加上就可。
题解链接

class Solution {
public:
    int mergeSort(int l, int r, vector<int> &data, vector<int> &tmp){
        if(l>=r) return 0;
        int m=(l+r)/2;
        int res = mergeSort(l, m, data, tmp)+mergeSort(m+1,r,data, tmp);
        int i=l, j=m+1;//i是左子数组头,j是右子数组头
        //合并阶段
        for(int k=l; k<=r; k++)//注意不要写成0 to n-1
            tmp[k]=data[k];//复制l到r这段到tmp
        for(int k=l; k<=r; k++){
            if(i==m+1)//左子数组比较完了
                data[k] = tmp[j++];
            else if(j==r+1 || tmp[i]<=tmp[j])//右子数组比较完或者左边当前<=右边当前,非逆序
                data[k] = tmp[i++];
            else{
                data[k] = tmp[j++];
                res += m-i+1;//左边当前>右边当前,是逆序,逆序对从i到m
                //res%=1000000007;
            }
        }
        return res;
        //return res%1000000007;
    }
    
    int reversePairs(vector<int> &nums) {
        vector<int> data=nums;
        vector<int> tmp(data.size());
        return mergeSort(0, data.size()-1, data, tmp);
    }
};

面试题52

双指针
一条长度a,一条b,公共长度c
A 走完自己这条再从B开头走到node,一共a+b-c
B走完自己这条再从A开头走到node,一共b+a-c

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        ListNode* A=pHead1, *B=pHead2;
        if(!A || !B) return nullptr;
        while(A!=B){
            if(A!=nullptr){
                A=A->next;
            }
            else A=pHead2;
            if(B!=nullptr){
                B=B->next;
            }
            else B=pHead1;
        }
        return A;
    }
};

面试题53

二分每次只能找一个数,这里要找多个重复的数,就改为两次二分找上下界。
题解链接+二分模板

class Solution {
public:
    int GetNumberOfK(vector<int> nums ,int target) {
        if(nums.empty()) return 0;
        
        int l=0, r=nums.size()-1;
        while(l<r){//第一轮,找左边界的target位置
            int mid=(l+r)/2;//两个数的话取左边的
            if(nums[mid] >= target) r=mid;
            else l=mid+1;
        }//这种会做到只剩一个数,用r是因为l的更新可能会出范围
        if(nums[r]!=target) return 0;
        //已经判断过没有这个数的情况,下面就当有这个数的情况处理,所以适合从0开始,
        //从L+1开始的话后面又可能没有这个数
        int L=r;//左边界
        l=0,r=nums.size()-1;
        while(l<r){
            int mid=(l+r+1)/2;//两个数的话取右边的
            if(nums[mid] <= target) l=mid;
            else r=mid-1;
        }
        return l-L+1;
    }
};

面试题54

中序加入v,是从小到大的序列。
这个是leetcode版本的带数组写法

class Solution {
public:
    void dfs(TreeNode* root, vector<int> &v){
        if(root==nullptr) return;
        dfs(root->left, v);
        v.push_back(root->val);
        dfs(root->right, v);
    }

    int kthLargest(TreeNode* root, int k) {
        vector<int> v;
        dfs(root, v);
        int n=v.size()-k;
        return v[n];
    }
};

牛客版本,题不一样,是找从小到大第k个,解法差不多,不带数组。

class Solution {
public:
    void dfs(TreeNode* proot, int &k, int &ans){
    //注意这里&k,&ans,否则里面dfs的时候会进去错误的k
        if(!proot) return;
        dfs(proot->left, k, ans);
        //if(k==0) return;
        k--;
        if(k==0){
            ans=proot->val;
            return;
        }
        dfs(proot->right, k, ans);
    }
    
    int KthNode(TreeNode* proot, int k) {
        // write code here
        int ans=-1;
        dfs(proot, k, ans);
        return ans;
    }
};

面试题55

class Solution {
public:
    int depth=0;
    int TreeDepth(TreeNode* pRoot) {
        if(pRoot==nullptr) return 0;
        if(!pRoot->left && !pRoot->right) return 1;
        //这句可以去掉
        else return 1+max(TreeDepth(pRoot->left), TreeDepth(pRoot->right));
    }
};

面试题56

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型vector 
     * @return int整型vector
     */
    vector<int> FindNumsAppearOnce(vector<int>& array) {
        // write code here
        //找到所有数异或以后为1的最低位,按这个位划分数组,两个数能分到不同组里
        int temp=0;
        for(auto i:array){
            temp^=i;
        }
        int mask=1;
        while((temp&mask)==0){
            mask<<=1;
        }
        int left=0, right=0;
        for(auto i:array){
            if((i & mask)==0) left^=i;
            else right^=i;
        }
        vector<int> v;
        if(left>right) swap(left, right);
        v.push_back(left);
        v.push_back(right);
        return v;
    }
};

面试题57

空间n,时间n

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        //哈希set扫一遍可行
        unordered_set<int> st;
        vector<int> v;
        for(auto num:array){
            if(st.find(num)!=st.end()){
                v.push_back(num);
                v.push_back(sum-num);
                break;
            }
            st.insert(sum-num);
        }
        return v;
    }
};

双指针空间1

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        //哈希set扫一遍可行
        unordered_set<int> st;
        vector<int> v;
        int i=0, j=array.size()-1;
        while(i<j){
            if(array[i]+array[j]==sum){
                v.push_back(array[i]);
                v.push_back(array[j]);
                break;
            }
            else if(array[i]+array[j]<sum) i++;
            else j--;
            
        }
        return v;
    }
};

面试题58

class Solution {
public:
    string LeftRotateString(string str, int n) {
        int slen=str.size();
        if(slen==0) return str;
        n=n%slen;
        if(n==0) return str;
        return str.substr(n)+str.substr(0,n);
    }
};

知识

&位运算后面==,要在位运算位置打括号,位运算优先低于==
mask<<1不能改mask,要mask<<=1才行,或者mask=mask<<1更清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值