1给定两个可能有环也可能无环的单链表,头节点head1和head2
请实现一个函数,如果两个链表相交,请返回相交的第一个节点。如果不相交返回null
要求如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)
容器法:用哈希表遍历
两个链表要不均有环,要不均无环,有环还可分为入环节点是否相同
#include<iostream>
#include<unordered_map>
using namespace std;
class node {
public:
int value;
node* next;
node(int val):value(val),next(nullptr){}
};
/*得到第一个入环节点:先设置两个快慢指针,均从头开始,一个一次跳两步
一个一次跳一步,直到两指针相遇后,一个从相遇点出发,一个从头出发,一次跳一步
第二次相遇点即为入环节点*/
node* getLoopNode(node* head) {
if (head == nullptr || head->next == nullptr || head->next->next == nullptr)
return nullptr;
node* slow = head;
node* fast = head;
while (slow != fast)
{
if (fast->next == nullptr || fast->next->next == nullptr) {
return nullptr;
}
fast = fast->next->next;
slow = slow->next;
}
fast = head;
if (slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
/*没有环时候的相遇:先分别计算出两条链表的长度l1,l2,长的链表链表先走abs(l1-l2)步,然后
两个链表一起走,走到相同时即为第一个相交点*/
node* noLoop(node* head1,node* head2)
{
if (head1 == nullptr || head2 == nullptr)
return nullptr;
node* cur1 = head1;
node* cur2 = head2;
int n = 0;
while (cur1->next != nullptr) {
n++;
cur1 = cur1->next;
}
while (cur2->next != nullptr) {
n--;
cur2 = cur2->next;
}
if (cur1 != cur2) {
return nullptr;
}
cur1 = (n > 0) ? head1 : head2;
cur2 = (cur1 == head1) ? head2 : head1;
n = abs(n);
while (n != 0) {
n--;
cur1 = cur1->next;
}
while (cur1 != cur2) {
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}
/*两个链表不可能一个有环一个无环,所以此时讨论均有环情况*/
node* bothLoop(node* head1, node* loop1, node* head2, node* loop2)
{
node* cur1 = nullptr;
node* cur2 = nullptr;
if (loop1 == loop2)//两个入环节点一样时,按照刚刚的方法即可确认出
{
cur1 = head1;
cur2 = head2;
int n = 0;
while (cur1 != loop1) {
n++;
cur1 = cur1->next;
}
while (cur2 != loop2) {
n--;
cur2 = cur2->next;
}
cur1 = (n > 0) ? head1 : head2;
cur2 = (cur1 == head1) ? head2 : head1;
n = abs(n);
while (n != 0) {
n--;
cur1 = cur1->next;
}
while (cur1 != cur2) {
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}
//入环节点不一样,此时可能不相遇,也可能在环上不同位置,所以先要弄清是否相交
else{
cur1 = loop1->next;
while (cur1 != loop1) {
if (cur1 == loop2) {
return loop1;
}
cur1 = cur1->next;
}
return nullptr;
}
}
//最后整合
node* getIntersectNode(node* head1, node* head2) {
if (head1 == nullptr || head2 == nullptr) {
return nullptr;
}
node* loop1 = getLoopNode(head1);
node* loop2 = getLoopNode(head2);
if (loop1 == nullptr && loop2 == nullptr) {
return noLoop(head1, head2);
}
if (loop1 != nullptr && loop2 != nullptr) {
return bothLoop(head1, loop1, head2, loop2);
}
return nullptr;
}
2二叉树先序、中序、后序的非递归遍历
#include<iostream>
#include<stack>
using namespace std;
class node {
public:
int value;
node* left;
node* right;
node(int v) : value(v), left(nullptr), right(nullptr) {}
};
void preOrder(node* head)
{
if (head != nullptr)
{
stack<node*> s;
s.push(head);
while (!s.empty())
{
head = s.top();
s.pop();
cout << head->value;
if (head->right != nullptr)
{
s.push(head->right);
}
if (head->left != nullptr)
{
s.push(head->left);
}
}
}
}
void inOrder(node* head) {
cout << "in-order: ";
if (head != nullptr) {
stack<node*> s;
while (!s.empty() || head != nullptr) {
if (head != nullptr) {
s.push(head);
head = head->left;
}//一路向左左到极点
else {
head = s.top();
s.pop();
cout << head->value << " ";
head = head->right;
}
}
}
cout << endl;
}
//后序遍历,由于为左右根,反过来为根右左,所以可以将前序遍历做改动,之后用栈逆序即可
void postOrder1(node* head) {
cout << "pos-order: ";
if (head != nullptr) {
stack<node*> s1;
stack<node*> s2;
s1.push(head);
while (!s1.empty()) {
head = s1.top();
s1.pop();
s2.push(head);
if (head->left != nullptr) {
s1.push(head->left);
}
if (head->right != nullptr) {
s1.push(head->right);
}
}
while (!s2.empty()) {
cout << s2.top()->value << " ";
s2.pop();
}
}
cout << endl;
}
void postOrder2(node* head) {
cout << "pos-order: ";
if (head != nullptr) {
stack<node*> s;
node* c = nullptr;
while (!s.empty() || head != nullptr) {
if (head != nullptr) {
s.push(head);
head = head->left;
}
else {
c = s.top();
if (c->right != nullptr && head != c->right) {
head = c->right;
}
else {
cout << c->value << " ";
s.pop();
head = c;
}
}
}
}
cout << endl;
}