来源:CodeTop 待补充
补充题4. 手撕快速排序
class Solution {
public:
void quickSort(int left,int right,vector<int> &nums)
{
if(left>=right) return;
int i=left;
int j=right;
int pivot=rand()%(right-left+1)+left;//要用差值来rand,比如递归的右边不是从0开始计数的⭐
swap(nums[pivot],nums[left]);//取随机一个数,每次都取最左边的超时
int base=nums[left];
while(i<j)
{
while(nums[j]>=base&&i<j) j--;//⭐
while(nums[i]<=base&&i<j) i++;//⭐
swap(nums[i],nums[j]);
}
swap(nums[i],nums[left]);
quickSort(left,i-1,nums);
quickSort(i+1,right,nums);
}
vector<int> sortArray(vector<int>& nums) {
quickSort(0,nums.size()-1,nums);
return nums;
}
};
补充知识:
704. 二分查找
class Solution {
public:
int search(vector<int>& nums, int target) {
int l=0;
int r=nums.size()-1;
while(l<=r)
{
int mid=l+(r-l)/2;
if(nums[mid]==target) return mid;
else if(nums[mid]<target) l=mid+1;
else if(nums[mid]>target) r=mid-1;
}
return -1;
}
};
160. 相交链表
使用set
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
set<ListNode*>res;
ListNode *temp=headA;
while(temp)
{
res.insert(temp);
temp=temp->next;
}
temp=headB;
while(temp)
{
if(res.count(temp)) return temp;
else temp=temp->next;
}
return NULL;
}
};
双指针法:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA||!headB) return nullptr;
ListNode *A=headA;
ListNode *B=headB;
while(A!=B)
{
if(A==nullptr) A=headB;
else A=A->next;
if(B==nullptr) B=headA;
else B=B->next;
}
return A;
}
};
232. 用栈实现队列
class MyQueue {
public:
stack<int> instack;//先产生两个栈
stack<int> outstack;
void in2out(stack<int> &instack,stack<int> &outstack)
{//两个栈的输入
if(outstack.empty())
{
while(!instack.empty())
{
outstack.push(instack.top());
instack.pop();
}
}
}
MyQueue() {}
void push(int x)
{//推入到接收的栈
instack.push(x);
}
int pop()
{//弹出输出的栈
if(outstack.empty()) in2out(instack,outstack);
int x=outstack.top();
outstack.pop();
return x;
}
int peek() {//输出top元素
if(outstack.empty()) in2out(instack,outstack);
return outstack.top();
}
bool empty() {//判断两个栈是不是空的
return outstack.empty()&&instack.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
1. 两数之和
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int,int>res;//用一个map存储值和下标
for(int i=0;i<nums.size();i++)
{
auto it=res.find(target-nums[i]);//找是否存在另一个对应的数字
if(it!=res.end()) return {it->second,i};//如果存在,返回下标和当前搜索到的下标
res[nums[i]]=i;//如果不存在,就存进去
}
return {};
}
};
14. 最长公共前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
int le=strs[0].length();
for(int i=0;i<strs.size();i++)
le=le<strs[i].length()?le:strs[i].length();
string record = strs[0].substr(0,le);
for(int i=0;i<strs.size();i++)
for(int j=0;j<le;j++)
if(record[j]!=strs[i][j])
record=record.substr(0,j); //参数=起始位置+截取长度
return record;
}
};
21. 合并两个有序链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode *fakeHead=new ListNode(-1);
ListNode *head=fakeHead;
while(list1&&list2)
{
if(list1->val<=list2->val)
{
head->next=list1;
head=head->next;
list1=list1->next;
}
else
{
head->next=list2;
head=head->next;
list2=list2->next;
}
}
if(list1) head->next=list1;
if(list2) head->next=list2;
return fakeHead->next;
}
};
494. 目标和
class Solution {
public:
int method=0;
void dfs(vector<int> &nums,int target,int k)
{
if(target==0&&k==nums.size()) //注意k要到nums.size(),因为相当于k是步数,最短为1
{
method++;
return;
}
if(k<nums.size())dfs(nums,target-nums[k],k+1);//注意控制k的大小
if(k<nums.size())dfs(nums,target+nums[k],k+1);//注意控制k的大小
}
int findTargetSumWays(vector<int>& nums, int target) {
if(nums.size()==0) return 0;//注意处理长度为0的情况
if(nums.size()==1) return nums[0]==target||nums[0]==-target;//处理长度为1的情况
dfs(nums,target,0);//处理长度为2的情况
return method;
}
};
25. K 个一组翻转链表
补充题5. 手撕归并排序
189. 旋转数组
227. 基本计算器 II
不大聪明的解题思路
class Solution {
public:
int calculate(string s) {
stack<int> num;//存数字
stack<char> sym;//存字符
string temp;//存字符串
for(int i=0;i<s.length();i++)
{
if(s[i]>='0'&&s[i]<='9')//处理数字
{
while(i<s.length()&&s[i]>='0'&&s[i]<='9')
{
temp+=s[i];
i++;
}
num.push(atoi(temp.c_str()));
temp="";
i--; //后退一步
}
else if(s[i]=='+'||s[i]=='-')//+-放后面
{
sym.push(s[i]);
}
else if(s[i]=='/')//除法进行处理
{
int x=num.top();
num.pop();
while(s[i]>'9'||s[i]<'0') i++;//跳过空格
while(i<s.length()&&s[i]>='0'&&s[i]<='9')
{
temp+=s[i];
i++;
}
int y=(atoi(temp.c_str()));
num.push(x/y);
temp="";
i--;
}
else if(s[i]=='*')//乘法处理
{
int x=num.top();
num.pop();
while(s[i]>'9'||s[i]<'0') i++;//跳过空格
while(i<s.length()&&s[i]>='0'&&s[i]<='9')
{
temp+=s[i];
i++;
}
int y=(atoi(temp.c_str()));
num.push(x*y);
temp="";
i--;
}
else continue;
}
stack<int> num1;//反过来进行加减法
stack<char> sym1;
while(!num.empty())
{
num1.push(num.top());
num.pop();
}
while(!sym.empty())
{
sym1.push(sym.top());
sym.pop();
}
while(!sym1.empty())
{
int x=num1.top();num1.pop();
int y=num1.top();num1.pop();
if(sym1.top()=='+')
{
num1.push(x+y);
sym1.pop();
}
else if(sym1.top()=='-')
{
num1.push(x-y);
sym1.pop();
}
}
return num1.top();
}
};
大聪明解法
class Solution {
public:
int calculate(string s) {
vector<int> nums;//用vector存比stack方便
char sign='+';//优先设一个符号,类似于链表设一个头节点方便计算
int num=0;//统计数字
for(int i=0;i<s.length();i++)
{
if(s[i]<='9'&&s[i]>='0')//对数字进行处理
{
num=num*10+(s[i]-'0');
}
if(i==s.length()-1||s[i]>'9'||s[i]<'0'&&s[i]!=' ')//对符号进行处理
{
switch(sign)
{
case '+': nums.push_back(num);break;//是+-先存起来
case '-': nums.push_back(-num);break;
case '*': nums[nums.size()-1]=nums[nums.size()-1]*num;break;//是乘除,优先进行处理
case '/': nums[nums.size()-1]=nums[nums.size()-1]/num;break;
}
sign=s[i];//存下一个符号
num=0;//更新数字
}
if(s[i]==' ')continue;
}
int res=0;//计算总数值
for(int i=0;i<nums.size();i++) res+=nums[i];
return res;//返回总答案
}
};
567. 字符串的排列
这道题只能说和我理解的子串不一个意思
子串:S2长度等于S1长度的子串,包含S1中的所有字符
class Solution {
public:
bool checkInclusion(string s1, string s2) {
vector<int> res1(26,0);
vector<int> res2(26,0);
if(s1.length()>s2.length()) return false;
for(int i=0;i<s1.length();i++)
{
res1[s1[i]-'a']++;
res2[s2[i]-'a']++;
}
if(res1==res2) return true;
for(int i=s1.length();i<s2.length();i++)
{
res2[s2[i]-'a']++;
res2[s2[i-s1.length()]-'a']--;
if(res1==res2) return true;
}
return false;
}
};
141. 环形链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *slow=head;
ListNode *fast=head;
while(fast)
{
if(!fast->next) return false;
fast=fast->next->next;
slow=slow->next;
if(slow==fast) return true;
}
return false;
}
};
31. 下一个排列
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int i=nums.size()-2;//找到nums的倒数第二位 1375【4】9631
while(i>=0&&nums[i]>=nums[i+1]) i--;//找出第一个不是按降序(从左至右)排列的数字
if(i>=0)
{
int j=nums.size()-1;//1375【4】9[6]31
while(j>=0&&nums[i]>=nums[j])j--;//找到第一个比之前找到的数字大的数字
swap(nums[i],nums[j]);//交换这两个数字 1375【6】9[4]31
}
reverse(nums.begin()+i+1,nums.end());//因为之前是降序的,反过来,让这个数字不要过大 1375【6】13[4]9 i的位置不变,如果是降序的,直接就被替换成了升序的
}
};
15. 三数之和
32. 最长有效括号
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> st;//先写一个栈
int ans=0;//一个存最大数量的数字
for(int i=0,start=0;i<s.length();i++)
{
if(s[i]=='(') st.push(i);//如果是正常的左括号,输入到栈中
else if(s[i]==')')//如果是右括号,进入判断程序
{
if(st.empty()) start=i+1;//如果整个栈是空的,证明没有匹配的左括号,更新统计起点
else if(!st.empty())//如果栈不为空,证明有匹配的左括号
{
st.pop();//先将左括号弹出
if(st.empty()) ans=max(ans,i-start+1);//如果完全匹配,那么用现在的 i-start+1就是最长的长度
else if(!st.empty()) ans =max(ans,(i-(st.top()+1)+1));//如果不完全匹配,证明匹配的是内层的左括号,内层左括号下标为st.top()+1
//因此ans=i-(st.top()+1)+1
}
}
}
return ans;//返回最长的长度
}
};