面试题52. 两个链表的第一个公共节点
注意:
- 如果两个链表没有交点,返回 null.
- 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
分析
方法一:双指针法
- 用两个指针p,q分别遍历A,B链表;
- 当p遍历A到末尾时,重新定位p到B的头结点;当q遍历到B的末尾时,重新定位q到A的头结点;
- 直至两节点相遇
- 时间复杂度:O(m+n)
- 空间复杂度:O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *node1 = headA;
ListNode *node2 = headB;
/*
if(node1!=NULL)
node1=node1->next;
else
node1=headB;
if(node2!=NULL)
node2=node2->next;
else
node2=headA;
*/
while (node1 != node2) {
node1 = node1 != NULL ? node1->next : headB;
node2 = node2 != NULL ? node2->next : headA;
}
return node1;
}
};
方法2:双指针提前法
计算两个链表的长度差值m,让较长的链表先走m步,然后两个链表再同时遍历,相遇时就是该节点
时间复杂度:O(n)
空间复杂度:O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *node1 = headA;
ListNode *node2 = headB;
int l1=len(headA);
int l2=len(headB);
/*让较长的链表先提前走*/
if(l1>l2)
{
int m=l1-l2;
while(m--)
{
headA=headA->next;
}
}
else
{
int m=l2-l1;
while(m--)
{
headB=headB->next;
}
}
/*此时两链表同时开始遍历,相遇时,返回该节点即可*/
while(headA!=headB)
{
headA=headA->next;
headB=headB->next;
}
return headB;
}
/*计算链表长度*/
int len(ListNode *head)
{
int n=0;
while(head)
{
n++;
head=head->next;
}
return n;
}
};
面试题32 - II. 从上到下打印二叉树 II
分析
C++ 二叉树的层序遍历BFS
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>res;
if(root==NULL)return res;
queue<TreeNode*>q;
q.push(root);//根节点入队列
while(!q.empty()){
vector<int>r;
int l=q.size();
for(int i=0;i<l;i++){ //当前层节点都在队列中,依次取出
TreeNode* t=q.front();
r.push_back(t->val);
q.pop();
if(t->left)q.push(t->left);
if(t->right)q.push(t->right);
}
res.push_back(r);
}
return res;
}
};
带main函数的二叉树层次遍历
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct TreeNode
{
int val;
TreeNode *left, *right;
TreeNode(int x): val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode *root){
vector<int> res(0);
if(root==NULL) return res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
TreeNode *p= q.front();
res.push_back(p->val);
q.pop();
if(p->left != NULL) q.push(p->left);
if(p->right != NULL) q.push(p->right);
}
return res;
}
};
// 以下为测试
int main()
{
Solution sol;
vector<int> res;
TreeNode *root = new TreeNode(1);
root->right = new TreeNode(2);
root->right->left = new TreeNode(3);
res=sol.PrintFromTopToBottom(root);
for(int i:res)
printf("%d ",i); // 此处为vector遍历的方法,C++11标准支持
return 0;
}