赞
踩
面试题 01.01. 判定字符是否唯一
方法一:哈希表
比较原数组和哈希表的长度,如果相等,说明没有重复元素;
class Solution {
public:
bool isUnique(string astr) {
int n=astr.size();
unordered_set<char> ret;
for(auto c:astr){
ret.insert(c);
}
return ret.size()==n;
}
};
方法二:位运算 可以利用一个int类型的变量(mask)
class Solution {
public:
bool isUnique(string astr) {
int mask = 0;
for (char& i : astr) {
if (mask & (1 << (i - 'a'))) return false;
mask |= (1 << (i - 'a'));
}
return true;
}
};
时间复杂度O(N) 空间复杂度O(1)
方法一:先排序再判断是否相等
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
sort(s1.begin(),s1.end());
sort(s2.begin(),s2.end());
return s1==s2;
}
};
方法一:在原数组上修改 先遍历数组计算非空格字符的数量num
,然后计算空格数length-num
,然后扩充数组的长度,最后利用双指针遍历 遇到空格就插入“%20”;
class Solution { public: string replaceSpaces(string S, int length) { int num=0; for(int i=0;i<length;i++){ if(S[i]!=' ') num++; } int kong=length-num; S.resize(num+kong*3); int j=S.size()-1; for(int i=length-1;i>=0;i--){ if(S[i]!=' ')S[j--]=S[i]; else{ S[j--]='0'; S[j--]='2'; S[j--]='%'; } } return S; } };
时间复杂度O(N) 空间复杂度O(1)
方法一:哈希表
class Solution {
public:
bool canPermutePalindrome(string s) {
unordered_set<char> st;
for(auto c: s){
if(st.count(c)) st.erase(c);
else st.insert(c);
}
return st.size()<=1;
}
};
时间复杂度O(N) 空间复杂度O(N)
方法一:一次遍历
class Solution { public: bool oneEditAway(string first, string second) { int n1=first.size(); int n2=second.size(); if(abs(n1-n2)>1) return false; if(first==second) return true; int count=0; int i=0,j=0; while(i <n1 && j <n2){ if(first[i++] == second[j++]){ continue; } count++; if(count > 1) return false; if( n1> n2){ j--; }else if(n1<n2){ i--; } } return true; } };
时间复杂度O(N) 空间复杂度O(1)
方法一:一次遍历
class Solution { public: string compressString(string S) { if(S.size()==0) return S; string ans=""; int cnt=1; char ch=S[0]; for(int i=1; i < S.size();i++){ if(ch ==S[i]) cnt++; else { ans+=ch+to_string(cnt); ch=S[i]; cnt=1; } } ans+=ch+to_string(cnt); return ans.size()>=S.size() ? S:ans; } };
时间复杂度O(N) 空间复杂度O(1)
方法一:翻转代替旋转 首先进行对角线翻转 然后进行竖轴翻转
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n=matrix.size();
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
swap(matrix[i][j],matrix[j][i]);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n/2;j++)
swap(matrix[i][j],matrix[i][n-1-j]);
}
}
};
时间复杂度O(N^2) 空间复杂度O(1)
方法二:原地旋转
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n=matrix.size();
for(int i=0;i<n/2;i++){
for(int j=0;j<(n+1)/2;j++){
int temp = matrix[i][j];
matrix[i][j]=matrix[n-j-1][i];
matrix[n-j-1][i]=matrix[n-i-1][n-j-1];
matrix[n-i-1][n-j-1] = matrix[j][n-i-1];
matrix[j][n-i-1]=temp;
}
}
}
};
时间复杂度O(N^2) 空间复杂度O(1)
方法一:先用数组将零元素的坐标存下来 然后修改为0;
class Solution { public: void setZeroes(vector<vector<int>>& matrix) { if(matrix.size() ==0 || matrix[0].size()==0) return ; vector<pair<int,int>> ret; for(int i=0;i<matrix.size();i++){ for(int j=0;j<matrix[0].size();j++){ if(matrix[i][j]==0) ret.push_back({i,j}); } } for(int i=0;i<ret.size();i++){ int n1=ret[i].first; int n2=ret[i].second; for(int j=0;j<matrix[0].size();j++){ matrix[n1][j]=0; } for(int k=0;k<matrix.size();k++){ matrix[k][n2]=0; } } } };
时间复杂度O(NM)
方法一:将s1和s1拼接 然后在拼接后的s1中找s2
class Solution { public: bool isFlipedString(string s1, string s2) { if(s1.size() != s2.size()) return false; s1+=s1; int n1=0,n2=0; while( n1 < s1.size() && n2 < s2.size()){ if(s1[n1]==s2[n2]){ n1++; n2++; } else { n2=0; n1=n1-n2+1; } } return n2==s2.size(); } };
时间复杂度O(N) 空间复杂度O(1)
方法二:使用标记数组
class Solution { public: void setZeroes(vector<vector<int>>& matrix) { int m=matrix.size(); int n=matrix[0].size(); vector<int> row(m),col(n); for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(matrix[i][j]==0) row[i]=col[j]=true; } } for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(row[i] || col[j]) matrix[i][j]=0; } } } };
时间复杂度O(MN) 空间复杂度O(M+N)
方法一:哈希表
class Solution { public: ListNode* removeDuplicateNodes(ListNode* head) { if(!head) return nullptr; unordered_set<int> st; ListNode* curr=head; st.insert(curr->val); while(curr->next){ if(st.count(curr->next->val)){ curr->next=curr->next->next; }else{ st.insert(curr->next->val); curr=curr->next; } } return head; } };
时间复杂度O(N) 空间复杂度O(N)
方法二:双循环
class Solution { public: ListNode* removeDuplicateNodes(ListNode* head) { if(!head) return nullptr; ListNode* curr=head; while(curr){ ListNode* pre=curr; while(pre->next){ if(pre->next->val==curr->val){ pre->next=pre->next->next; }else{ pre=pre->next; } } curr=curr->next; } return head; } };
时间复杂度O(N^2) 空间复杂度O(1)
方法一:双指针 前指针先走k步,后指针开始走;当前指针走到末尾,则后指针就是倒数第k个指针
class Solution {
public:
int kthToLast(ListNode* head, int k) {
if(!head) return -1;
ListNode* pre=head,*curr=head;
while(k--){
pre=pre->next;
}
while(pre){
pre=pre->next;
curr=curr->next;
}
return curr->val;
}
};
时间复杂度O(N) 空间复杂度O(1)
方法一:将下一个节点赋值给当前节点 然后删除下一个节点
class Solution {
public:
void deleteNode(ListNode* node) {
node->val=node->next->val;
node->next=node->next->next;
}
};
方法一:分割链表
class Solution { public: ListNode* partition(ListNode* head, int x) { ListNode* smallhead=new ListNode(0); ListNode* small=smallhead; ListNode* largehead=new ListNode(0); ListNode* large=largehead; while(head){ if(head->val<x){ small->next=head; small=small->next; }else{ large->next=head; large=large->next; } head=head->next; } large->next=nullptr; small->next=largehead->next; return smallhead->next; } };
时间复杂度O(N) 空间复杂度O(1)
方法一:递归
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
return addcore(l1,l2,0);
}
ListNode* addcore(ListNode* l1,ListNode* l2,int carry){
if(!l1 && !l2 && carry==0) return nullptr;
int val = carry + (l1? l1->val : 0) + (l2? l2->val : 0);
carry = val / 10;
ListNode* res = new ListNode (val%10);
res -> next=addcore(l1 ? l1->next: nullptr,l2? l2->next:nullptr,carry);
return res;
}
};
方法二:迭代 先对应节点求和再加上进位
class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { if(!l1 && !l2) return nullptr; ListNode* head=new ListNode(-1),*p=head; int carry=0; while(l1 || l2 || carry){ int sum=0; if(l1){ sum+=l1->val; l1=l1->next; } if(l2){ sum+=l2->val; l2=l2->next; } sum+=carry; ListNode* node=new ListNode(sum%10); carry=sum/10; p->next=node; p=p->next; } return head->next; } };
时间复杂度O(N)
方法一:先将值复制到数组中后用双指针法
class Solution { public: bool isPalindrome(ListNode* head) { vector<int> vals; while (head != nullptr) { vals.emplace_back(head->val); head = head->next; } for (int i = 0, j = (int)vals.size() - 1; i < j; ++i, --j) { if (vals[i] != vals[j]) { return false; } } return true; } };
时间复杂度O(N) 空间复杂度O(N)
方法二:快慢指针 用快慢指针找到中点 然后将后半段反转
方法一:哈希表
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
unordered_set<ListNode *> visited;
while (head != nullptr) {
if (visited.count(head)) {
return head;
}
visited.insert(head);
head = head->next;
}
return nullptr;
}
};
时间复杂度O(N) 空间复杂度O(N)
方法二:快慢指针
class Solution { public: ListNode *detectCycle(ListNode *head) { if(!head) return nullptr; ListNode *fast=head,*slow=head; while(fast){ slow=slow->next; if(fast->next==nullptr){ return nullptr; } fast=fast->next->next; if(slow==fast){ ListNode* node=head; while(node!=slow){ node=node->next; slow=slow->next; } return node; } } return nullptr; } };
时间复杂度O(N) 空间复杂度O(1)
方法一:深度优先遍历 利用一个visited的数组来记录是否遍历了边 每次遍历:1.看是否能直接转到 2.如果不到就考虑这一条是target的情况,然后更新新的target 3然后回溯
class Solution { public: bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) { int k=graph.size(); vector<bool> visite(k,false); for(int i=0;i<k;i++){ if(graph[i][0]==start && graph[i][1]==target){ return true; } } return dfs(visite,graph,start,target); } bool dfs(vector<bool>& visite,vector<vector<int>>& graph,int start,int target){ for(int i=0;i<graph.size();i++){ if(!visite[i]){ if(graph[i][0]==start && graph[i][1]==target) return true; visite[i]=true; if(graph[i][1]==target && dfs(visite,graph,start,graph[i][0])) return true; visite[i]=false; } } return false; } };
方法一:迭代算法 先序遍历
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.size()==0) return nullptr;
return sortA(nums,0,nums.size()-1);
}
TreeNode* sortA(vector<int>& nums,int low,int high){
if(low>high) return nullptr;
int mid=(low+high)>>1;
TreeNode* tmp=new TreeNode(nums[mid]);
tmp->left=sortA(nums,low,mid-1);
tmp->right=sortA(nums,mid+1,high);
return tmp;
}
};
时间复杂度O(N) 空间复杂度O(logN)
方法:广度优先搜索
class Solution { public: vector<ListNode*> listOfDepth(TreeNode* tree) { vector<ListNode*> res; if(!tree) return {}; queue<TreeNode*> q; q.push(tree); while(!q.empty()){ int n=q.size(); ListNode* tmp=new ListNode(0); ListNode* ret=tmp; for(int i=0;i<n;i++){ TreeNode* node=q.front(); q.pop(); if(node->left) q.push(node->left); if(node->right) q.push(node->right); ListNode* temp=new ListNode(node->val); ret->next=temp; ret=ret->next; } res.push_back(tmp->next); } return res; } };
时间复杂度O(N) 空间复杂度O(N)
class Solution {
public:
bool isValidBST(TreeNode* root) {
if(!root) return true;
return dechose(root,LONG_MIN,LONG_MAX);
}
bool dechose(TreeNode* node,long long low,long long high){
if(!node) return true;
if(node->val <=low || node->val >=high){
return false;
}
return dechose(node->left,low,node->val) && dechose(node->right,node->val,high);
}
};
时间复杂度O(N) 空间复杂度O(N)
class Solution { public: bool isValidBST(TreeNode* root) { stack<TreeNode*> st; if(!root) return true; long long inorder=LONG_MIN; while(!st.empty() || root!=nullptr){ while(root != nullptr){ st.push(root); root=root->left; } root=st.top(); st.pop(); if(root->val <=inorder) return false; inorder=root->val; root=root->right; } return true; } };
时间复杂度O(N) 空间复杂度O(N)
思路:迭代法
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if (root == nullptr || p == nullptr)
return nullptr;
if (p->val >= root->val)
return inorderSuccessor(root->right, p);
else {
TreeNode* left = inorderSuccessor(root->left, p);
return left ? left : root;
}
}
};
时间复杂度O(N) 空间复杂度O(1)
思路:首先查找root->val
class Solution { public: TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) { if(!root) return nullptr; TreeNode* pre=nullptr; while(root->val !=p->val){ if(root->val <p->val) root=root->right; else { pre=root; root=root->left; } } if(root->right ==nullptr) return pre; else{ root=root->right; while(root->left != nullptr){ root=root->left; } return root; } } };
时间复杂度O(N)
思路: 如果root为空,或rootp或rootq,返回root;分别将root->left、root->right作为根节点、调用自身,得到返回值left、right;若left为空,若right不为空,返回root,否则返回left;否则返回right。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==nullptr || root==p || root==q) return root;
TreeNode* left=lowestCommonAncestor(root->left,p,q);
TreeNode* right=lowestCommonAncestor(root->right,p,q);
if(left != nullptr){
return right ? root : left;
}
else return right;
}
};
时间复杂度O(N) 空间复杂度O(N)
思路:存储父节点
思路:迭代算法
class Solution {
public:
bool checkSubTree(TreeNode* t1, TreeNode* t2) {
if(t1==nullptr || t2==nullptr) return false;
return recure(t1,t2) || checkSubTree(t1->left,t2) || checkSubTree(t1->right,t2);
}
bool recure(TreeNode* A ,TreeNode* B){
if(B==nullptr) return true;
if(A==nullptr || A->val!=B->val) return false;
return recure(A->left,B->left) && recure(A->right,B->right);
}
};
时间复杂度O(MN) 空间复杂度O(M)
class Solution { private: int Depth(TreeNode* root){ if(!root) return 0; return max(Depth(root->left),Depth(root->right))+1; } public: int ret=0; int pathSum(TreeNode* root, int sum) { if(root==nullptr) return ret; int depth = Depth(root); int path[depth]; memset(path,0,sizeof(int)*depth); dfs(root,sum,path,0); return ret; } void dfs(TreeNode* curr,int sum,int* path,int level){ if(curr == nullptr) return; path[level] = curr->val; int currSum=0; for(int i=level;i>=0;i--){ currSum +=path[i]; if(currSum == sum) ++ret; } dfs(curr->left, sum, path, level+1); dfs(curr->right, sum, path, level+1); } };
思路:动态规划
class Solution { public: int waysToStep(int n) { if(n==1) return 1; if(n==2) return 2; if(n==3) return 4; int ret=0,first=1,second=2,third=4; for(int i=3;i<n;i++){ ret=((first+second)%1000000007+third)%1000000007; first=second; second=third; third=ret; } return ret; } };
普通遍历
class Solution {
public:
int findMagicIndex(vector<int>& nums) {
for(int i=0;i<nums.size();i++){
if(nums[i]==i) return i;
}
return -1;
}
};
时间复杂度O(N)空间复杂度O(1)
思路:二分法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。