class Solution {
public:
bool isUnique(string astr) {
if(astr.size()==0)return true;
unordered_set<char>myset={astr[0]};
for(int i=1;i<astr.size();i++)
{
if(myset.find(astr[i])!=myset.end())
return false;
myset.insert(astr[i]);
}
return true;
}
};
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
unordered_map<char, int> mp;
for(int i = 0; i < s1.size(); i ++)
mp[s1[i]] ++;
for(int i = 0; i < s2.size(); i ++)
mp[s2[i]] --;
unordered_map<char, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it++)
{
if(it->second != 0) return false;
}
return true;
}
};
这题也是见了不知道多少次了,先补充一下数组,再从后往前双指针。
class Solution {
public:
string replaceSpaces(string S, int length) {
int count=0;
for(int i=0;i<length;i++)
{
if(S[i]==' ')
{
count++;
}
}
if(count==0)return S;
int p1=length-1;
int p2=length+2*count -1;
while(p1>=0&&p1<=p2)
{
if(S[p1]!=' ')
{
S[p2--]=S[p1--];
}
else
{
p1--;
S[p2--]='0';
S[p2--]='2';
S[p2--]='%';
}
}
return S.substr(0,length+2*count);
}
};
这种题目就是秒杀。
class Solution {
public:
bool canPermutePalindrome(string s) {
//最多允许一个字符出现奇数次,其余字符必须都出现偶数次
unordered_map<char,int>mp;
for(int i=0;i<s.size();i++)
{
mp[s[i]]++;
}
int odd_count=1;//奇数
for(auto it=mp.begin();it!=mp.end();it++)
{
if(it->second%2 != 0)
{
if(odd_count==0)
{
return false;
}
else
{
odd_count--;
}
}
}
return true;
}
};
这题就是简单的分类讨论即可。
class Solution {
public:
bool oneEditAway(string first, string second) {
//字符数相差大于1,false
//字符数相等,判断first和second中有两个及以上个字符不相同,返回false
//字符数相差等于1,将长字符串删掉一个后和短的比较是否完全相同
int first_len = first.size();
int second_len = second.size();
if (first_len == second_len)
{
int count = 0;
for (int i = 0; i<first_len; i++)
{
if (first[i] != second[i])
count++;
}
if (count >= 2)return false;
return true;
}
else if (abs(first_len - second_len) == 1)
{
if (first_len>second_len)
{
return fun(first, second);
}
else
{
return fun(second, first);
}
}
else
{
return false;
}
}
bool fun(string&long_str, string&short_str)
{
for (int i = 0; i<long_str.size(); i++)
{
string temp = long_str;
temp.erase(i, 1);//string& erase ( size_t pos = 0, size_t n = npos );
if (isEqual(temp, short_str))
return true;
}
return false;
}
bool isEqual(const string&s1, const string&s2)
{
for (int i = 0; i<s1.size(); i++)
{
if (s1[i] != s2[i])
return false;
}
return true;
}
};
这道题双指针很简单,唯一需要注意的是需要使用to_string函数,将数值转化为字符串并返回对应的字符串。
class Solution {
public:
string compressString(string S) {
//双指针遍历
string res;
int i=0,j=0;
while(i<S.size())
{
int count=0;
while(j<S.size()&&S[i]==S[j])
{
count++;
j++;
}
res.append(1,S[i]);
res.append(to_string(count));//必须使用to_string函数!!!
i=j;
}
if(res.size()<S.size())
return res;
return S;
}
};
这题应该还有其他更好的方法,我自己第一感觉是这个方法:
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
set<int>rows;
set<int>cols;
for (int i = 0; i<matrix.size(); i++)
for (int j = 0; j<matrix[0].size(); j++)
{
if (matrix[i][j] == 0)
{
rows.insert(i);
cols.insert(j);
}
}
for (auto it = cols.begin(); it != cols.end(); it++)//按列清零
for (int i = 0; i<matrix.size(); i++)
{
matrix[i][*it] = 0;
}
for (auto it = rows.begin(); it != rows.end(); it++)//按行清零
for (int i = 0; i<matrix[0].size(); i++)
{
matrix[*it][i] = 0;
}
}
};
思路:如果 s2 为 s1 轮转而成,那么 s2 前一部分和 s1 的后一部分子串相等,s2 的后一部分和 s1 的前一部分子串相等。
使用s1 = “waterbottle”, s2 = "erbottlewat"进行分析就可以定出要截取的长度。
class Solution {
public:
bool isFlipedString(string s1, string s2) {
int m = s1.size(), n = s2.size();
if(m != n) return false;
if(m == 0) return true;
for(int i = 0; i < m; i ++){
if(s1[i] == s2[0]){
//string类中对==也进行重载了,很方便
if(s1.substr(0, i) == s2.substr(m - i) && s1.substr(i) == s2.substr(0, m - i))
return true;
}
}
return false;
}
};
class Solution {
public:
//双指针
int kthToLast(ListNode* head, int k) {
ListNode*first=new ListNode(-1);//哨兵结点
first->next=head;
ListNode*p1=head,*p2=head;
while(k--)
{
p1=p1->next;
}
while(p1!=NULL)
{
p1=p1->next;
p2=p2->next;
}
delete first;
first=NULL;
return p2->val;
}
};
极其无聊的题目,没有意义。
class Solution {
public:
void deleteNode(ListNode* node) {
//无法访问前驱结点,只好把当前结点变为下一节点,然后删除下一节点
node->val=node->next->val;
node->next=node->next->next;
}
};
这题很简单,就是题目的语文水平真是烂的要死。
//建立两个链表,一个用来存储小于x的值,一个用来存储大于等于x的值,最后将两个链表拼接起来即可;
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode*head1=new ListNode(-1);
ListNode*head2=new ListNode(-1);
ListNode*t1=head1,*t2=head2;
ListNode*t=head;
while(t!=NULL)
{
if(t->val<x)
{
t1->next=t;
t1=t1->next;
t=t->next;
t1->next=NULL;
}
else
{
t2->next=t;
t2=t2->next;
t=t->next;
t2->next=NULL;
}
}
t1->next=head2->next;
return head1->next;
}
};
这题还是挺好的,要考虑的特殊情况比较多,我修改了2次代码才AC。
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
bool carry=false;
ListNode*t1=l1,*t2=l2;
ListNode*new_head=new ListNode(-1);
ListNode*t=new_head;
while(t1!=NULL||t2!=NULL)
{
int sum1=t1==NULL?0:t1->val;
int sum2=t2==NULL?0:t2->val;
int sum=sum1+sum2;
if(carry)
{
sum++;
carry=false;
}
if(sum>=10)
{
carry=true;
sum-=10;
}
t->next=new ListNode(sum);
t=t->next;
if(t1!=NULL)
t1=t1->next;
if(t2!=NULL)
t2=t2->next;
}
if(carry)
{
t->next=new ListNode(1);
}
return new_head->next;
}
};
这题还是挺好的!
class Solution {
public:
bool isPalindrome(ListNode* head) {
//先用快慢指针找链表中点,再对后半段链表进行反转,最后比较两个链表是否相同即可
if(head==NULL||head->next==NULL)return true;//只有1个结点
ListNode*slow=head,*fast=head;
while(fast!=NULL&&fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
}
ListNode*back_new_head=reverseList(slow);
ListNode*t1=head;
ListNode*t2=back_new_head;
while(t2!=NULL)
{
if(t1->val!=t2->val)
return false;
t1=t1->next;
t2=t2->next;
}
return true;
}
ListNode*reverseList(ListNode*head)
{
ListNode*prev=NULL;
ListNode*cur=head;
while(cur!=NULL)
{
ListNode*temp=cur->next;
cur->next=prev;
prev=cur;
cur=temp;
}
return prev;
}
};
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode*t1=headA,*t2=headB;
int len1=0,len2=0;
while(t1!=NULL)
{
len1++;
t1=t1->next;
}
while(t2!=NULL)
{
len2++;
t2=t2->next;
}
int diff=abs(len2-len1);
t1=headA;
t2=headB;
if(len1>len2)
{
while(diff--)
{
t1=t1->next;
}
while(t1!=NULL&&t2!=NULL)
{
if(t1==t2)
return t1;
t1=t1->next;
t2=t2->next;
}
return NULL;
}
else
{
while(diff--)
{
t2=t2->next;
}
while(t1!=NULL&&t2!=NULL)
{
if(t1==t2)
return t1;
t1=t1->next;
t2=t2->next;
}
return NULL;
}
}
};
/*
1.判断有没有环
2.求出环中的结点个数
从两个指针相遇的结点开始出发,一边继续向前移动一边计数,当再次回到这个结点时,就可以得到环中的结点个数了。
3.找环的入口结点
先定义两个指针p1、p2指向链表头结点,如果环中有n个结点,则指针p1先在链表上向前移动n步,然后两个指针均以每次1步的速度向前移动。当p2与p1相遇时,相遇结点就是入口结点。
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==NULL)return NULL;
if(head->next==NULL)return NULL;
//step1
ListNode*fast=head,*slow=head;
while(fast!=NULL&&fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(slow==fast)
break;
}
if(slow!=fast)
return NULL;
//step2
int count=1;
slow=slow->next;
while(slow!=fast)
{
slow=slow->next;
count++;
}
//step3
slow=head;
fast=head;
while(count--)
{
fast=fast->next;
}
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
};
class TripleInOne {
private:
vector<int> s;
int stackSize;
int spointer[3];
public:
TripleInOne(int stackSize) {//constructor
s=vector<int>(stackSize*3,0);
spointer[0]=0 -1;//减1是因为最初栈为空
spointer[1]=stackSize -1;
spointer[2]=stackSize*2 -1;
this->stackSize=stackSize;
//第0个栈范围[0,stackSize-1]
//第1个栈范围[stackSize,2*stackSize-1]
//第2个栈范围[2*stackSize,3*stackSize-1]
}
void push(int stackNum, int value) {
if(spointer[stackNum]+1<(stackNum+1)*stackSize)//表示没有溢出
{
spointer[stackNum]++;
s[spointer[stackNum]]=value;
}
}
int pop(int stackNum) {
if(spointer[stackNum]>=stackNum*stackSize)//表示栈不为空
{
return s[spointer[stackNum]--];
}
else
{
return -1;
}
}
int peek(int stackNum) {
if(spointer[stackNum]>=stackNum*stackSize)//表示栈不为空
{
return s[spointer[stackNum]];
}
else
{
return -1;
}
}
bool isEmpty(int stackNum) {
if(spointer[stackNum]>=stackNum*stackSize)//表示栈不为空
{
return false;
}
else
{
return true;
}
}
};
class MinStack {
//思路:单栈,用pair压栈两个数,一个是正常元素,另一个是目前最小值
private:
stack<pair<int,int>>s;
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
if(s.empty())
{
s.push(make_pair(x,x));
}
else
{
s.push(make_pair(x,min(x,getMin())));
}
}
void pop() {
s.pop();
}
int top() {
return s.top().first;
}
int getMin() {
return s.top().second;
}
};
class StackOfPlates {
private:
list<stack<int>>ls;
int sz;//每个栈的最大容量
public:
//双向链表
StackOfPlates(int cap) {
sz=cap;
}
void push(int val) {
if(!ls.empty()&&ls.back().size()<sz)
{
ls.back().push(val);
}
else
{
stack<int>temp;
temp.push(val);
ls.push_back(temp);
}
}
int pop() {
if(sz==0)return -1;
if(ls.empty())return -1;
int ans = ls.back().top();
ls.back().pop();
if(ls.back().size()==0)
ls.pop_back();
return ans;
}
int popAt(int index) {
if(sz == 0) return -1;
if(index >= ls.size()) return -1;
list<stack<int>>::iterator it = ls.begin();
while(index --) ++it;
int ans = it->top();
it->pop();
if(it->size() == 0) ls.erase(it);
return ans;
}
};
这种题秒杀。
class MyQueue {
private:
stack<int>s1;
stack<int>s2;
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
s1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
int res;
if(!s2.empty())
{
res=s2.top();
s2.pop();
return res;
}
else
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
res=s2.top();
s2.pop();
return res;
}
}
/** Get the front element. */
int peek() {
if(!s2.empty())
{
return s2.top();
}
else
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
return s2.top();
}
}
/** Returns whether the queue is empty. */
bool empty() {
return s1.empty()&&s2.empty();
}
};
class SortedStack {
public:
stack<int>s1, s2;//s1是辅助栈
SortedStack() {
}
void push(int val) {
while (!s2.empty() && val > s2.top())
{
s1.push(s2.top());
s2.pop();
}
s2.push(val);
while (!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
void pop() {
if (!s2.empty())
s2.pop();
}
int peek() {
if (!s2.empty())
return s2.top();
return -1;
}
bool isEmpty() {
return s2.empty();
}
};
很简单的题。
class AnimalShelf {
private:
queue<vector<int>> queue_cat;
queue<vector<int>> queue_dog;
public:
AnimalShelf() {
}
void enqueue(vector<int> animal) {
if(animal[1]==0)//是猫
{
queue_cat.push(animal);
}
else
{
queue_dog.push(animal);
}
}
vector<int> dequeueAny() {
vector<int>temp;
if(queue_cat.empty()&&queue_dog.empty())
{
return {-1,-1};
}
else if(!queue_cat.empty()&&queue_dog.empty())
{
temp=queue_cat.front();
queue_cat.pop();
}
else if(queue_cat.empty()&&!queue_dog.empty())
{
temp=queue_dog.front();
queue_dog.pop();
}
else
{
if((queue_cat.front())[0]<(queue_dog.front())[0])//动物编号:猫 < 狗 猫先出
{
temp=queue_cat.front();
queue_cat.pop();
}
else
{
temp=queue_dog.front();
queue_dog.pop();
}
}
return temp;
}
vector<int> dequeueDog() {
vector<int>temp;
if(queue_dog.empty())
{
return {-1,-1};
}
else
{
temp=queue_dog.front();
queue_dog.pop();
return temp;
}
}
vector<int> dequeueCat() {
vector<int>temp;
if(queue_cat.empty())
{
return {-1,-1};
}
else
{
temp=queue_cat.front();
queue_cat.pop();
return temp;
}
}
};
非常经典的题!考查图的遍历DFS或BFS
法1.DFS
class Solution {
vector<bool> visited;
vector<vector<int>> adList;
public:
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
visited = vector<bool>(n,0);
adList = vector(n,vector<int>());
for (int i=0;i<graph.size();i++)
{
adList[graph[i][0]].push_back(graph[i][1]);//表示i-->adList[i][j]
}
return DFS(start,target);
}
bool DFS(int start,int target)
{
visited[start] = true;
bool result = false;
for(int i=0;i<adList[start].size();i++)
{
if (visited[adList[start][i]]==false)
{
if(adList[start][i]==target)
{
visited[adList[start][i]] =true;
return true;
}
result = DFS(adList[start][i],target);//完成后续递归
if(result==true)
return true;
}
}
return false;
}
};
法2:BFS
class Solution {
vector<bool> visited;
vector<vector<int>> adList;
public:
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
visited = vector<bool>(n, 0);
adList = vector(n, vector<int>());
for (int i = 0; i < graph.size(); i++)
{
adList[graph[i][0]].push_back(graph[i][1]);//表示i-->adList[i][j]
}
return BFS(start, target);
}
bool BFS(int start, int target)
{
queue<int> q;
int temp;
visited[start] = true;
q.push(start);
while (!q.empty())
{
temp = q.front();
q.pop();
for (int i = 0; i < adList[temp].size(); i++)
{
if (visited[adList[temp][i]] == false)
{
visited[adList[temp][i]] = true;
if (adList[temp][i] == target)
{
return true;
}
else
{
q.push(adList[temp][i]);
}
}
}
}
return 0;
}
};
简单的递归:
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.size()==0)return NULL;
return DFS(nums,0,nums.size()-1);
}
TreeNode*DFS(vector<int>&nums,int low,int high)
{
if(low>high)
{
return NULL;
}
int mid=(low+high)/2;
TreeNode*root=new TreeNode(nums[mid]);
root->left=DFS(nums,low,mid-1);
root->right=DFS(nums,mid+1,high);
return root;
}
};
简单的BFS,秒杀
class Solution {
private:
vector<ListNode*>res;
queue<TreeNode*>myqueue;
public:
//简单的BFS
vector<ListNode*> listOfDepth(TreeNode* tree) {
if(tree==NULL)return{};
myqueue.push(tree);
BFS();
return res;
}
void BFS()
{
while(!myqueue.empty())
{
int size=myqueue.size();
ListNode*dummy=new ListNode(-1);
ListNode*cur=dummy;
for(int i=0;i<size;i++)
{
TreeNode*temp=myqueue.front();
myqueue.pop();
cur->next=new ListNode(temp->val);
cur=cur->next;
if(temp->left!=NULL)
{
myqueue.push(temp->left);
}
if(temp->right!=NULL)
{
myqueue.push(temp->right);
}
}
res.push_back(dummy->next);
}
}
};
秒杀
//简单的DFS
class Solution {
public:
bool isBalanced(TreeNode* root) {
if(root==NULL)return true;
if(abs(depth(root->left)-depth(root->right))>1)return false;
return isBalanced(root->left)&&isBalanced(root->right);
}
int depth(TreeNode*root)
{
if(root==NULL)
{
return 0;
}
return max(depth(root->left),depth(root->right))+1;
}
};
DFS,中序遍历
class Solution {
private:
long pre = LONG_MIN;
public:
bool isValidBST(TreeNode* root) {
if (!root)
return true;
if (!isValidBST(root->left))//左子树已经完成判断
return false;
if (root->val <= pre)
return false;
pre = root->val;
return isValidBST(root->right);//右子树已经完成判断
}
};
法1:开一个数组直接保存中序遍历序列,然后再慢慢找
class Solution {
private:
vector<TreeNode*>res;
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
DFS(root);
res.push_back(NULL);
for(int i=0;i+1<res.size();i++)
{
if(p==res[i])
return res[i+1];
}
return NULL;
}
void DFS(TreeNode*root)
{
if(root==NULL)
return;
DFS(root->left);
res.push_back(root);
DFS(root->right);
}
};
法2:漂亮的DFS,,利用BST的特性,一步到位
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if (root == NULL || p == NULL) return NULL;
if (p->val >= root->val)
{
return inorderSuccessor(root->right, p);//要找的目标结点一定在右子树中
} else //要找的目标结点在左子树中,或者目标结点就是根结点
{
TreeNode*left = inorderSuccessor(root->left, p);
return left ? left : root;
}
}
};
这题是非常好的递归题!!
当我们用递归去做这个题时不要被题目误导,应该要明确一点
这个函数的功能有三个:给定两个节点p和q
1.如果p和q都存在,则返回它们的公共祖先;
2.如果只存在一个,则返回存在的一个;
3.如果p和q都不存在,则返回NULL;
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL)return NULL;
if (root == p || root == q)
return root;
TreeNode*left = lowestCommonAncestor(root->left, p, q);//假设已经完成
TreeNode*right = lowestCommonAncestor(root->right, p, q);//假设已经完成
if (left == NULL)//说明p、q都在右子树
return right;
if (right == NULL)//说明p、q都在左子树
return left;
if (left&&right)//说明p、q一个在左子树,另一个在右子树
return root;
return NULL;
}
};
class Solution {
public:
bool checkSubTree(TreeNode* t1, TreeNode* t2) {
if(t1==NULL&&t2==NULL)return true;
if(t1==NULL&&t2!=NULL)return false;
return isSametree(t1,t2)
|| checkSubTree(t1->left,t2)||checkSubTree(t1->right,t2);
}
bool isSametree(TreeNode* t1, TreeNode* t2)
{
if(t1==NULL&&t2==NULL)return true;
if(t1==NULL||t2==NULL)return false;
return t1->val==t2->val&&isSametree(t1->left,t2->left)&&isSametree(t1->right,t2->right);
}
};
经典的双递归题。
class Solution {
private:
vector<int>cur;
vector<vector<int>>res;
public:
int pathSum(TreeNode* root, int sum) {
if(root==NULL)return 0;
DFS_2(root,sum);
return res.size();
}
void DFS_1(TreeNode*root,int sum)//以root为根结点开始找
{
if(root==NULL)return;
cur.push_back(root->val);
if(sum-root->val==0)
{
res.push_back(cur);
}
DFS_1(root->left,sum-root->val);
DFS_1(root->right,sum-root->val);
cur.pop_back();
}
void DFS_2(TreeNode*root,int sum)//对每一个结点都当作根结点试一试
{
if(root==NULL)return;
DFS_1(root,sum);
DFS_2(root->left,sum);
DFS_2(root->right,sum);
}
};
class Solution {
public:
//1.把 N 中 i~j 的位置先置零
//2.把 M 左移 i 位后和 N 相加
int insertBits(int N, int M, int i, int j) {
int t=0;
for(int x=i;x<=j;x++)
{
t|=(1<<x);//把i~j 的位置先置1
}
t=~t;
N&=t;
M<<=i;
return M+N;
}
};
class Solution {
public:
string printBin(double num) {
string res = "0.";
int i = 30; // 因为题中要求用32位以内的二进制表示,所以 "0." 计为两位,所以把i初始化为30
while (num > 0. && i--) {
num *= 2;
if (num >= 1) {
res.push_back('1');
--num;
}
else res.push_back('0');
}
return num != 0. ? "ERROR" : res;
}
};
挺好的题,思路我觉得很不错!
class Solution {
public:
int reverseBits(int num) {
int res=0;
int cur=0,prev=0;
//从低位开始
while(num)
{
if(num&1)
{
cur++;
}
else//当前bit是0
{
if(cur+prev+1>res)
{
res=cur+prev+1;
}
prev=cur;
cur=0;
}
num>>=1;
}
//别忘记最后还需要额外判断一次
if(cur+prev+1>res)
{
res=cur+prev+1;
}
return res;
}
};
显然,这题唯一需要注意的就是负数的右移情况。
class Solution {
public:
int convertInteger(int A, int B)
{
return convertInteger((unsigned int)A,(unsigned int)B);
}
int convertInteger(unsigned int A, unsigned int B) {
int t1,t2;
int count=0;
while(A||B)
{
t1=A&1;
t2=B&1;
if(t1!=t2)
count++;
A>>=1;
B>>=1;
}
return count;
}
};
很经典的位运算题目!
//运算时的转换
//当运算涉及两种类型时,较小的类型将会被转换为较大的类型,也就是表达力低的类型会被转换为表达力高的类型。
//各类型表达能力从低到高排列为:
//int-->unsigned int-->long-->unsigned long-->float-->double-->long double
class Solution {
public:
int exchangeBits(int num) {
return ((num&0xaaaaaaaa)>>1) | ((num&0x55555555)<<1);
//提取奇数位,并右移1位到偶数位置,注意,0xaaaaaaaa的类型是unsigned int,所以int&unsigned int运算时,先把int提升为unsigned int,然后unsigned int&unsigned int。而unsigned int进行右移操作是不会有问题的,高位会补0
//提取偶数位,并左移1位到奇数位置
}
};