面试题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更清楚。