体系班第十节

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;
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值