解题思路:看题目意思,得到本体的核心就在于模拟 加法竖式。
方法一:(自己写)
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// if(!l1->val) return l2;
// if(!l2->val) return l1;
ListNode* a = l1;
ListNode* b = l2;
ListNode* head = new ListNode(0);
ListNode* c = head;
while (a || b) {
int n1 = a ? a->val : 0;
int n2 = b ? b->val : 0;
int t = n1 + n2 + c->val;
c->val = t % 10;
// cout << "c" << c->val << endl;
if (a)
a = a->next;
if (b)
b = b->next;
if (a || b || (t / 10 > 0)) {
cout << "t" << t << endl;
c->next = new ListNode(t / 10);
}
c = c->next;
}
return head;
}
};
巧妙之处:1.两个链表长度不一样,怎么解决?(参考示例三)如果,链表结点存在就返回结点值,否则返回0。
int n1 = a ? a->val : 0;
int n2 = b ? b->val : 0;
2.这一块我觉得是处理最棒的地方。如果a,b未到头肯定要继续创建。还有一种情况,就是最后有高位产生。还有一点,直接让c里面存放进位的值,省了一个变量。
if (a || b || (t / 10 > 0)) {
cout << "t" << t << endl;
c->next = new ListNode(t / 10);
}
方法一:
思路:建立一维数组,如果访问过,就设为visied【i】==true;如果再访问到visied【i】==true,就说明有环。再想一下,如果便利的话,i++,并不会形成闭环,并且这个还需要建立一位数组,怎么办呢?我们不防直接将访问过得链表的值更改。(当然,这只是投机取巧的方法,实际上,高级代码师,都会保证链表的完整性。)
class Solution {//偷鸡法
public:
bool hasCycle(ListNode *head) {
if(!head||!head->next) return false;
ListNode *p=head;
while(p){
if(p->val==10001)
return true;
p->val=10001;
p=p->next;
}
return false;
}
};
方法二:哈希表法
思路: 我们可以使用哈希表来存储所有已经访问过的节点。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。
代码:
public:
bool hasCycle(ListNode *head) {
if(!head||!head->next) return false;
unordered_set<ListNode*> visited;
ListNode *p=head;
while(p){
if(visited.count(p))
return true;
visited.insert(p);
p=p->next;
}
return false;
}
};
语法解释:
方法三:龟兔赛跑法:(经典算法,判断有无环)
假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;如果该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。
https://assets.leetcode-cn.com/solution-static/141/2.png
class Solution {//龟兔赛跑算法
public:
bool hasCycle(ListNode *head) {
if(!head||!head->next) return false;
ListNode *slow=head;
ListNode *fast=head->next;
while(slow!=fast){
if(!fast||!fast->next)
return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
讲解:为了便于理解,不如现设一个头结点,即起跑线,龟兔同时从该点出发,兔子每次走两步,乌龟每次走一步。如果兔子和乌龟重合说明这条跑道有环。如果,双方没有重合,并且兔子先到达终点,就说明没有环。这样代码就更改如下:
class Solution {//龟兔赛跑算法
public:
bool hasCycle(ListNode *head) {
if(!head||!head->next) return false;
ListNode *dummy=new ListNode(0,head);
ListNode *slow=dummy;
ListNode *fast=dummy;
while(slow!=fast||slow==dummy){
if(!fast||!fast->next)
return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
注意:题目要求 :不允许修改 链表。所以,上一题的第一个做法,pass。
方法一:上一题的哈希表法,可以进行改编。使用哈希表来存储所有已经访问过的节点,同时设置变量记录哈希表中元素数量。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,返回元素个数-1,即为所求,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。