leetcode141
给定一个链表,判断链表中是否有环。
class Solution
{
public:
bool hasCycle(ListNode *head) { //判断链表中是否有环
if(head==NULL){
return false;
}
ListNode *l1=head;
ListNode *l2=l1->next;
while(l1!=NULL){
while(l2!=NULL){
if(l2->next==l1){
return true;
}
else{
l2=l2->next;
}
}
l1=l1->next;
}
return false;
}
};
上来想到的还是这种两个指针两重循环的垃圾写法,结果不出所料的超时了,再想想好一点的写法。。。
class Solution
{
public:
bool hasCycle(ListNode* head) { //两个运动员位于同意起点head
ListNode* faster{ head }; //快的运动员
ListNode* slower{ head }; //慢的运动员
if (head == NULL) //输入链表为空,必然不是循环链表
return false;
while (faster != NULL && faster->next != NULL) {
faster = faster->next->next; //快的运动员每次跑两步
slower = slower->next; //慢的运动员每次跑一步
if (faster == slower) //他们在比赛中相遇了
return true; //可以断定是环形道,直道不可能相遇
}
return false; //快的运动员到终点了,那就是直道,绕圈跑不会有终点
}
};
利用这种快慢指针,非常容易的转化成了一遍循坏,还有没有更快一点的呢?
class Solution {
public:
bool hasCycle(ListNode* head) {
class Solution {public:
bool hasCycle(ListNode *head) {
if(!head)
return false;
auto pt = head;
unordered_set<ListNode*> s;
while(s.find(pt) == s.end()) {
s.insert(pt);
pt = pt->next;
if(!pt)
return false;
}
return true;
}
};
利用hash表来完成,也同样不难
leetcode160
编写一个程序,找到两个单链表相交的起始节点。
第一个想到的是之前做王道数据结构书上的算法
遍历得到两个链表的长度,求长度差diff;
两个指针分别指向两个链表的头结点,让更长的那个链表的指针先走diff步后,两个指针在同时移动,遇到的第一个相同的节点就是他们的公共节点。
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
ListNode *CommomNode = nullptr;
if(headA != nullptr && headB != nullptr) {
int countA = 0;
int countB = 0;
ListNode *pNodeA = headA;
ListNode *pNodeB = headB;
while(pNodeA != nullptr) {
countA++;
pNodeA = pNodeA->next;
}
while(pNodeB != nullptr) {
countB++;
pNodeB = pNodeB->next;
} //长的链表先走
pNodeA = headA;
pNodeB = headB;
int diff = abs(countA - countB);
if(countA > countB) {
for(int i = 0;i < diff;i++) {
pNodeA = pNodeA->next;
}
}
else if(countA < countB) {
for(int i = 0;i < diff;i++) {
pNodeB = pNodeB->next;
}
}
while(pNodeA!= nullptr && pNodeB != nullptr) {
if(pNodeA == pNodeB) {
CommomNode = pNodeA;
break;
}
pNodeA = pNodeA->next;
pNodeB = pNodeB->next;
}
}
return CommomNode;
}
当然也可以用双指针暴力破解法,就不写了
再想想其他方法
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
unordered_set<ListNode *> st;
while(headA!=NULL){
st.insert(headA);
headA=headA->next;
}
while(headB!=NULL){
if(st.count(headB))
return headB;
headB=headB->next;
}
return NULL;
}
};
看leetcode官方给出的一种答案真的给惊艳到了,代码竟然可以这么浪漫,真的好遗憾自己以前不曾发现过代码的美妙和乐趣
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { //
if (headA == NULL || headB == NULL)
return NULL;
ListNode *pA = headA, *pB = headB;
while (pA != pB) {
pA = pA == NULL ? headB : pA->next;
pB = pB == NULL ? headA : pB->next;
}
return pA;
}
};
这个方法翻译成中文就是:
我来到 你的城市
走过你来时的路
leetcode203
删除链表中等于给定值 val 的所有节点。
很简单的题,就是一遍遍历呗
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* prev = dummy;
while(prev->next) {
if(prev->next->val == val) {
ListNode* tmp = prev->next;
prev->next = prev->next->next;
delete tmp;//对于链表来说要释放空间不要忘记了!
}
else {
prev = prev->next;
}
}
return dummy->next;
}
};