算法通关村第一关——链表经典问题之求两个单链表的公共子节点和判断链表是否有回文序列笔记

学习笔记

1.两个单链表的公共子节点

输入两个单链表,找到它们的第一个公共结点,例如:


怎么搞?首先我们很容易就会想起暴力解法,就像冒泡排序一样,先定住A链中的一个结点a1,然后比较所有B链中的结点地址,然后再定住A链中的第二个结点a2,然后再比较B链中所有的结点地址,如此循环往复直到找到公共结点。😊

这种方法很容易想到,但是时间复杂度高,pass!

我们现在思考一下单链表的定义,看看下面这个图是不是两个单链表:


很显然,不是。Why?

注意看,这两个链表公共结点c1的next到底是哪个?是a5还是b4🤔?链表是环环相扣的,核心就是一个结点只能有一个后继。

就好像我国的一夫一妻制一样,你可以有很多人爱你(两个结点例如a3和b2的后继可以相同,都是c1),但你只能爱一个人(一个结点例如c1的后继只能是一个)【😭哭死,纯爱战神应声倒地】

结论:两个单链表的公共结点之后一定都是公共结点。

那不妨我们从链表的末尾开始遍历,但是我们只知道每个链表的头指针,想想哪个数据结构有类似的功能——栈,先进后出💪。

定义两个栈,利用头指针分别把两个链表从头压入栈中,在一个个访问栈顶元素,如果两个栈的栈顶元素相同就保存下来,然后弹出此时栈顶元素,接着判断下两个栈顶元素是否相同,直到不相同为止。

LinkNode* findFirstCommonByStack(LinkNode* headA, LinkNode* headB) {
  std::stack<LinkNode*> stackA;
  std::stack<LinkNode*> stackB;

  //把链表A的所有结点压入栈中
  while (headA != nullptr) {
      stackA.push(headA);
      headA = headA->next;
  }
  //把链表B的所有结点压入栈中
  while (headB != nullptr) {
      stackB.push(headB);
      headB = headB->next;
  }

  LinkNode* commonNode = nullptr;
  //两个栈都没空
  while (!stackA.empty() && !stackB.empty()) {
      if (stackA.top() == stackB.top()) {
          //返回公共结点
          commonNode = stackA.top();
          //弹出栈顶元素
          stackA.pop();
          stackB.pop();
      }else{
          break;
      }
  }
  return commonNode;
}

findFirstCommonByStack()接受两个参数,分别是两个链表的头指针,时间复杂度是O(m + n),其中m和n分别是两个链表的长度。

注意:C++标准库用使用栈要引入stack的头文件:

#include <stack>

当然还可以使用Hash表会更简单,这个我们后面会详细讲解。

2. 判断链表是否有回文序列

示例:

  • 输入:链表1->2->2->1
  • 输出:true

思路一:将链表中所有的结点值按顺序保存到数组中,从数组两端向中间对比。这种方法很容易想到,但是会被认为逃避链表,不可取。

思路二:反转链表到一个newLink中,同时遍历比较两个链表,只要有一个不相同都是false

思路三:利用栈先进后出的特点保存链表的逆序,然后重新遍历链表,一遍出栈一边比较。这里我们演示思路三:

//Palindrome是回文的意思
bool isPalindrome(LinkNode* head) {
  LinkNode* node = head;
  //创建一个栈压入每个结点的地址
  std::stack<LinkNode*> stack1;
  while (node != nullptr) {
      stack1.push(node);
      node = node->next;
  }
  while (head != nullptr) {
      if (head->elem != stack1.top()->elem) {
          return false;
      }
      head = head->next;
  }
  return true;
 }

注意👀,这里创建的栈保存的是每个结点的地址,stack1.top()是一个地址,stack1.top()->elem是它的值才能用于比较。这道题是LeetCode234,上面还有超多解法,大家可以去逛逛。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值