234:回文链表
将链表存入数组再判断:
Python有语法糖,不需要双指针法,直接就可以翻转比较。
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
array = []
currNode = head
while currNode is not None:
array.append(currNode.val)
currNode = currNode.next
return array == array[::-1]
C++采用双指针法,也很简单直接。
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> vals;
ListNode *cur = head;
while(cur) {
vals.push_back(cur->val);
cur = cur->next;
}
int n = vals.size();
int i = 0, j = n-1;
while(i <= j) {
if(vals[i] == vals[j]) {
i++;
j--;
}
else {
return false;
}
}
return true;
}
};
利用栈的方法来比较:
class Solution {
public:
bool isPalindrome(ListNode* head) {
stack<int> s;
ListNode *cur = head;
while(cur) {
s.push(cur->val);
cur = cur->next;
}
cur = head;
while(!s.empty()) {
if(s.top() == cur->val) {
cur = cur->next;
s.pop();
}
else {
return false;
}
}
return true;
}
};
性能最优的方法:时间O(n),空间O(1),快慢指针找到链表中点,只翻转一半的链表,再进行比较。
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(!head || !head->next) return true;
ListNode *slow = head, *fast = head; //快慢指针,确保只翻转了一半的链表
ListNode *pre = nullptr, *cur = slow;
while(fast && fast->next) {
cur = slow;
slow = slow->next;
fast = fast->next->next;
cur->next = pre;
pre = cur;
}
//奇偶分开讨论
if(fast) { //链表偶数个节点时,fast会为null
slow = slow->next; //奇数个节点,需要跳过中间节点比较两边的节点
}
while(cur && slow) {
if(cur->val != slow->val) return false;
cur = cur->next;
slow = slow->next;
}
return true;
}
};
9. 回文数
一种方法是把 int 变量转化为 string 然后用双指针法从两端开始比较,另外一种是翻转 int 但是担心会溢出,仔细分析可知只翻转一半即可,但要注意int的位数为奇数时翻转的部分会多一位,所以return部分要稍加改动。
class Solution {
public:
bool isPalindrome(int x) {
if(x < 0 || ((x % 10 == 0) && (x != 0)) ) return false;
int y = 0;
while(x > y) {
y = y * 10 + x % 10;
x /= 10;
}
return (x == y) || (y/10 == x);
}
};
125. 验证回文串
采用双指针法,从两端往中间走,非字母数字问题和大小写问题,用两个C++库函数就可以。
isalnum(char c):判断字符变量c是否为字母或数字,若是则返回非零,否则返回零。
tolower(char c):把字母字符转换成小写,非字母字符不做出处理。
class Solution {
public:
bool isPalindrome(string s) {
if(s.size() <= 1) return true;
int i = 0, j = s.size() - 1;
while (i<j) {
while(i<j && !isalnum(s[i])) {
i++;
}
while(i<j && !isalnum(s[j])) {
j--;
}
if(tolower(s[i]) != tolower(s[j])) {
return false;
}
i++;
j--; //漏掉这两行会导致第一次比较完就陷入死循环
}
return true;
}
};