有段时间没有练习了,链表回文串判断用到了栈。链式A+B将没有的项用0补充。链表有没有头节点,及结点和链表的区别,即pNode和pHead。
//#include<iostream> //using namespace std; // //class Base { //public: // Base(int j) : i(j) {} // virtual~Base() {} // void func1() { // i *= 10; // func2(); // } // int getValue() { // return i; // } //protected: // virtual void func2() { // i++; // } //protected: // int i; //}; // //class Child : public Base { //public: // Child(int j) : Base(j) {} // void func1() { // i *= 100; // func2(); // } //protected: // void func2() { // i += 2; // } //}; //int main() { // Base * pb = new Child(1); // pb->func1(); // cout << pb->getValue() << endl; ///12 // delete pb; //}
题目分析:
《方法1》:反转链表
可以将原始链表反转,判断反转以后的链表与原始链表是否完全一致,如果一致便返回true,如果不一致则返回false。反转链表需要额外的存储空间,不是特别优秀的方法。
《方法2》:栈实现
我们可以想到从中间节点向两侧开始比较,如果全部相同,则返回true,否则返回false,因为无法获得一个节点的前一个节点,这个时候我们可以想到用栈实现,先将链表前半部分的元素分别压入堆栈,然后在遍历后半部分元素的时候同时和栈顶元素进行比较,如果全部相等则返回true,否则返回false。
特别注意:因为我们不知道链表的的长度,可以通过快慢指针(一个指针每次移动两个,一个指针每次移动一个)来找到中间元素,这样整体只需要遍历链表一次,所需要的栈空间缩小为方法1的一半。
《方法3》:递归法
递归方法分为尾部递归和首部递归,还有中间递归,一般的尾部递归都可以用循环来实现,对于我们这道题目,递归的时候无法比较第一个元素和最后一个元素,即使知道最后一个元素,也无法获得最后一个元素的前一个元素。所以我们选择首部递归,先递归直到中间的元素,然后比较中间的元素,把比较结果返回,同时保存后半部分下一个要比较的元素(用引用传递可以,用二级指针也可以),递归返回后,如果是true,则继续比较,如果是false,则直接返回false。
《程序员面试金典》程序详解:
/***************************************************** * \file Palindrome listNode.cpp * \date 2016/05/05 17:16 题目描述 请编写一个函数,检查链表是否为回文。 给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。 测试样例: {1,2,3,2,1} 返回:true {1,2,3,2,3} 返回:false *****************************************************/ struct ListNode { int val; struct ListNode *next; ListNode(int x) :val(x), next(nullptr){} }; #include <iostream> #include <stack> using namespace std; class Palindrome { public: bool isPalindrome(ListNode* pHead) { // write code here ListNode *pNode = pHead; stack<int> s; while (pNode) { s.push(pNode->val); pNode = pNode->next; } pNode = pHead; while (pNode) { if (pNode->val==s.top()) { pNode=pNode->next; s.pop(); } else { return false; } } return true; } };
这个哥们总结的不错:
《程序员面试金典》程序详解:
题目描述
有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。
给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。
测试样例:
{1,2,3},{3,2,1}
返回:{4,4,4}
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) {} };*/ class Plus { public: ListNode* plusAB(ListNode* a, ListNode* b) { ; ListNode *retHead = ); ListNode *p = retHead; while (a || b || carry) { ; ; ; carry = (vala + valb + carry) / ; //进位 ListNode *tmp = new ListNode(val); p->next = tmp; p = p->next; a = a ? a->next : nullptr; b = b ? b->next : nullptr; } p->next = nullptr; return retHead->next; } };