大家好,我是开车的阿Q,自动驾驶的时代已经到来,没时间解释了,快和阿Q一起上车。作为自动驾驶系统工程师,必须要有最好的C++基础,让我们来一起刷题吧。
题目考察的知识点
链表,回文判断,字符串操作,双指针
题目解答方法的文字分析
这个题目需要解决两个主要任务:首先,判断整个链表是否为回文;其次,如果不是回文,要找到最大连续回文子链表。解决思路如下:
- 首先,我们实现一个名为 isPalindrome 的函数,用于判断给定链表是否为回文。为了做到这一点,我们使用递归的方法,并同时维护一个左指针 left 和从链表头部开始逐步移动的右指针 right。在递归过程中,我们不断比较 left 和 right 指向的节点的值,如果有值不相等的情况,则返回 false,否则返回 true。
- 如果整个链表不是回文,我们可以将链表中每个节点的值连接成一个字符串,然后从每个节点开始,向前和向后扩展,判断是否构成回文。我们维护两个指针 i 和 j,从每个节点开始扩展,如果 str[i] 和 str[j] 相等,则向两侧扩展。在这个过程中,我们记录扩展的范围,然后找到最大回文子链表的起始和结束位置。
- 最后,根据最大回文子链表的起始和结束位置,截取链表以获取最大回文子链表,并返回其头节点。
本题解析所用的编程语言
C++
完整且正确的编程代码
class Solution { public: ListNode* maxPalindrome(ListNode* head) { left = head; // 如果整个链表是回文,返回空链表 if (isPalindrome(head)) return nullptr; // 将链表中每个节点的值拼接成字符串 string str = ""; ListNode* p = head; while (p != nullptr) { str += to_string(p->val); p = p->next; } int start = 0, end = 0; for (int i = 0; i < str.length() - 1; i++) { // 向两侧扩展,得到回文的范围 vector<int> res1 = palindrome(str, i, i); vector<int> res2 = palindrome(str, i, i + 1); if (res1[1] - res1[0] > end - start) { start = res1[0]; end = res1[1]; } if (res2[1] - res2[0] > end - start) { start = res2[0]; end = res2[1]; } } start++; end--; // 找到最大回文子链表的起始节点 ListNode* startNode = head; end = end - start; while (head != nullptr) { if (start == 0) { startNode = head; break; } else { head = head->next; start--; } } // 找到最大回文子链表的结束节点 while (head != nullptr) { if (end == 0) { break; } else { head = head->next; end--; } } // 断开链表,只保留最大回文子链表 if (head != nullptr) { head->next = nullptr; } return startNode; } ListNode* left = nullptr; // 判断回文的递归函数 bool isPalindrome(ListNode* right) { if (right == nullptr) return true; bool result = isPalindrome(right->next); result = result && (left->val == right->val); left = left->next; return result; } // 向两侧扩展,判断回文的函数 vector<int> palindrome(string str, int i, int j) { while (i >= 0 && j < str.length()) { if (str[i] == str[j]) { --i; ++j; } else break; } return vector<int>{i, j}; } };