来源:CodeTop
腾讯音乐
142. 环形链表 II
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow=head;//用快慢指针来解答
ListNode *fast=head;
while(fast)
{
if(!fast->next) return NULL;//如果快指针到尾还没有解决问题,无环,返回NULL
if(fast->next) fast=fast->next->next;//如果快指针还能前进,继续
slow=slow->next;//slow指针移动
if(slow==fast)//当出现了环的入口,进入
{//此时只是在环的某个位置相遇,并不是环的入口,还需要查找
ListNode *p=head;//用数学逻辑判断
while(p!=slow)
{//从头部向前走,加slow继续移动,可以同时移动到环的如果
slow=slow->next;
p=p->next;
}
return slow;//返回环的入口
}
}
return NULL;
}
};
468. 验证IP地址
class Solution {
public:
string validIPAddress(string queryIP) {
//先判断:或者.
int flag1=0,flag2=0;
for(int i=0;i<queryIP.length();i++)
{
if(queryIP[i]=='.') flag1++;
if(queryIP[i]==':') flag2++;
}
if(flag1==3&&flag2==0)//如果是IPv4
{
int points=0;
int left=0;int right=0;
while(points<4)
{
string temp="";
while(right<queryIP.length()&&queryIP[right]!='.')
{
if(queryIP[right]>'9'||queryIP[right]<'0') return "Neither";//判断有没有不是数字的
temp+=queryIP[right];//加起来后续对数字大小进行判断
right++;//移动
}
if(queryIP[left]=='0'&&right-left!=1||right-left>3||right-left==0) return "Neither";//如果存在开头为0,且不是单数||过长||过短
if(atoi(temp.c_str())>255) return "Neither"; //数字过大⭐
left=right+1;right++;points++;//移动
}
return "IPv4";
}
if(flag2==7&&flag1==0)
{
int points=0;
int left=0;int right=0;
while(points<8)
{
while(right<queryIP.length()&&queryIP[right]!=':')
{
if(queryIP[right]<='Z'&&queryIP[right]>'F'||queryIP[right]>'f'&&queryIP[right]<'z') return "Neither";//超出十六进制
right++;//移动
}
if(right-left>4||right-left==0) return "Neither";//过长或过短
left=right+1;right++;points++;
}
return "IPv6";
}
return "Neither";
}
};
208. 实现 Trie (前缀树)
不会,问到就摆烂
743. 网络延迟时间
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
//------------------------------------------------------
map<int,map<int,int>> adj;//涉及到走来走去的,存图//注意写法❤
for(auto &time :times)//先将题目给的数据存起来
{//重点一:构件图的方法⭐
int from=time[0];int to=time[1];int cost_time=time[2];
adj[from][to]=cost_time;//转化为一张图,用map存,得到用时节点图
}
//------------------------------------------------------
//重点二:记录visited和使用的时间,set+vector⭐
set<int>visited;//确定访问了几个节点,用set自动去重排序
vector<int> use_time(n+1,INT_MAX);//记录到达每个节点消耗的时间,注意只有1-n,不是0-n
visited.insert(k);//访问点加入起点
use_time[k]=0;//记录起点用时为0
//------------------------------------------------------
//重点三:用队列模仿层序遍历走完整个图
queue<int>q;//约等于层序遍历
q.push(k);// 将起点打入
while(!q.empty())
{
int from=q.front();q.pop();visited.insert(from);//将队列投存储下来,推出,并且记为访问过的
for(auto &[to,cost_time]:adj[from])//注意写法❤
{//这个for就是从队列起点能到达的所有点都要更新
int time=use_time[from]+cost_time;//到达这个点花费的时间等于源头加消耗
if(use_time[to]>time)//取较小的时间且同时再更新一次图,如果本身是较小的时间就不更新图
{
use_time[to]=time;
q.push(to);
}
}
}
//------------------------------------------------------
if(visited.size()==n) return *max_element(use_time.begin()+1,use_time.end());//注意写法❤
return -1;
/*
if(visited.size()==n)
{
int max=0;
for(int i=1;i<use_time.size();i++)
{
if(use_time[i]>max) max=use_time[i];
}
return max;
}
return -1;
*/
}
};
23. 合并K个排序链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* merge2Lists(ListNode* l1,ListNode* l2)
{//简单的将两个有序链表合并的是实现
if(!l1) return l2;
if(!l2) return l1;
ListNode *startl1=l1;
ListNode *startl2=l2;
ListNode *fakehead=new ListNode(-1);
ListNode *head=fakehead;
while(startl1&&startl2)
{
if(startl1->val<=startl2->val)
{
head->next=startl1;
head=head->next;
startl1=startl1->next;
}
else
{
head->next=startl2;
head=head->next;
startl2=startl2->next;
}
}
if(startl1) head->next=startl1;
if(startl2) head->next=startl2;
return fakehead->next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size()==0) return {};//如果为空,返回空
if(lists.size()==1) return lists[0];//如果只有一个链表,直接返回
if(lists.size()==2) return merge2Lists(lists[0],lists[1]);//如果是两个链表,直接返回
//以下处理多个链表的情况
int l=0;int r=lists.size()-1;
while(l<r)
{//从两头开始混合
if(lists[l]&&lists[r])
{//如果都不为空,开始合并
lists[l]=merge2Lists(lists[l],lists[r]);
r--;//l不动,右边动
}
if(!lists[l]) l++;//如果开头l为空移动,到不为空的地方固定
if(!lists[r]) r--;//右边为空就移动到不为空的地方
}
return lists[l];//返回固定处的lists[l],合并过后的结果
}
};
206. 反转链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *curr=head;
ListNode *p=nullptr;
while(curr)
{
ListNode *temp=curr->next;
curr->next=p;
p=curr;
curr=temp;
}
return p;
}
};
378. 有序矩阵中第K小的元素
解法一:
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
vector<int> res;
for(int i=0;i<matrix.size();i++)
{
for(int j=0;j<matrix.size();j++)
{
res.push_back(matrix[i][j]);
}
}
sort(res.begin(),res.end());
return res[k-1];
}
};
解法二:(不理解right为什么取mid)
class Solution {
public:
int binary(vector<vector<int>> &matrix,int mid)
{
int i=matrix.size()-1;
int j=0;
int num=0;
while(i>=0&&j<matrix.size())
{
if(matrix[i][j]<=mid)
{
num+=i+1;
j++;//按竖着的形式计算小于mid的个数
}
else i--;
}
return num;
}
int kthSmallest(vector<vector<int>>& matrix, int k) {
int l=matrix[0][0];
int r=matrix[matrix.size()-1][matrix.size()-1];
while(l<r)
{
int mid=l+(r-l)/2;
if(binary(matrix,mid)>=k) r=mid;//大于k,证明这个数字取得太大了,因此需要调整右端
else l=mid+1;
}
return r;//此处返回l或者r其实都是一样的,因为最终l=r
}
};
21. 合并两个有序链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
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;
}
};
补充题21. 字符串相减
class Solution {
public:
string addStrings(string num1, string num2) {
//处理方法,倒位相加
int i=num1.length()-1;
int j=num2.length()-1;
string ans="";//存储答案
int add=0;//进位
while(i>=0||j>=0||add!=0)//ij分别处理当短了的情况,add处理当加完了数字,但是仍然存在进位的情况
{
int n1,n2;
if(i<0) n1=0;
else n1=num1[i]-'0';
i--;//如果数字位用完,用0填补,如果不是取出数字,i--
if(j<0) n2=0;
else n2=num2[j]-'0';
j--;//如果数字位用完,用0填补,如果不是取出数字,j--
int result=add+n1+n2;//处理该位数字和进位
ans+=('0'+result%10);
add=result/10;//注意进位
}
reverse(ans.begin(),ans.end());//翻转
return ans;//返回答案
}
};