#234回文链表
简单方法很简单(转成vector判断),难的方法有点难, 很巧妙
简单方法:
bool isPalindrome(ListNode* head) {
vector<int> vec;
ListNode* cur=head;
while(cur){
vec.push_back(cur->val);
cur=cur->next;
}
int start=0; int end=vec.size()-1;
while(start<=end){
if(vec[start]!=vec[end]) return false;
start++; end--;
}
return true;
}
难的方法:
学习随想录+一些自己的实现。要点:
1.找到LL中间点:
while (fast && fast->next) {
pre = slow;
slow = slow->next;
fast = fast->next->next;
}
pre->next = nullptr;
一定要用slow前面那个,然后前半段比后半段是奇数的话少一个,要使用slow整个就不对了。不知道怎么想出来的,但是测试一下是这样的
2.随想录的翻转和我写的略微有不同:其实不用管cur->next是不是null。但现在是第二遍做翻转LL写出来了,算是会了吧。
ListNode* reverseList(ListNode* head) {
ListNode* temp; // 保存cur的下一个节点
ListNode* cur = head;
ListNode* pre = nullptr;
while(cur) {
temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur->next = pre; // 翻转操作
// 更新pre 和 cur指针
pre = cur;
cur = temp;
}
return pre;
}
整体代码:
bool isPalindrome(ListNode* head) {
if (head->next == nullptr) return true;
ListNode* slow = head; // 慢指针,找到链表中间分位置,作为分割
ListNode* fast = head;
ListNode* pre = head; // 记录慢指针的前一个节点,用来分割链表
while (fast && fast->next) {
pre = slow;
slow = slow->next;
fast = fast->next->next;
}
pre->next = nullptr;
ListNode* cur1 = head; // 前半部分
ListNode* cur2 = reverseList(slow);
while (cur1) {//equal of cur1 longer
if (cur1->val != cur2->val) return false;
cur1 = cur1->next;
cur2 = cur2->next;
}
return true;
}
ListNode* reverseList(ListNode* head){
ListNode* cur=head;
ListNode* pre=nullptr;
ListNode* tmp=nullptr;
while(cur && cur->next){
tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
cur->next=pre;
return cur;
}
#143重排链表
用纯粹的链表法就会和#234回文LL很像,我想的&&我写的:
void reorderList(ListNode* head) {
if(!head->next) return;
ListNode* slow=head;
ListNode* fast=head;
ListNode* pre=head;
while(fast && fast->next){
pre=slow;
slow=slow->next;
fast=fast->next->next;
}
pre->next=nullptr;
//slow is the head2, LL1 shorter
ListNode* cur1=head;
ListNode* cur2=reverse(slow);
ListNode* tmp;
ListNode* tmp2;
while(cur1 && cur1->next){
tmp=cur1->next;
tmp2=cur2->next;
cur1->next=cur2;
cur2->next=tmp;
cur1=tmp;
cur2=tmp2;
}
cur1->next=cur2;
}
ListNode* reverse(ListNode* head){
ListNode* pre=nullptr;
ListNode* cur=head;
ListNode* tmp=nullptr;
while(cur){
tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
思路和随想录一样的:
但是随想录主函数实现和我略有不同:
void reorderList(ListNode* head) {
if (head == nullptr) return;
// 使用快慢指针法,将链表分成长度均等的两个链表head1和head2
// 如果总链表长度为奇数,则head1相对head2多一个节点
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next && fast->next->next) {
fast = fast->next->next;
slow = slow->next;
}
ListNode* head1 = head;
ListNode* head2;
head2 = slow->next;
slow->next = nullptr;
// 对head2进行翻转
head2 = reverseList(head2);
// 将head1和head2交替生成新的链表head
ListNode* cur1 = head1;
ListNode* cur2 = head2;
ListNode* cur = head;
cur1 = cur1->next;
int count = 0; // 偶数取head2的元素,奇数取head1的元素
while (cur1 && cur2) {
if (count % 2 == 0) {
cur->next = cur2;
cur2 = cur2->next;
} else {
cur->next = cur1;
cur1 = cur1->next;
}
count++;
cur = cur->next;
}
if (cur2 != nullptr) { // 处理结尾
cur->next = cur2;
}
if (cur1 != nullptr) {
cur->next = cur1;
}
}
其他方法:1. LL放到vec然后一前一后双指针 2.把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表 (从来没写过双向队列,真是神奇的东西)
void reorderList(ListNode* head) {
deque<ListNode*> que;
ListNode* cur = head;
if (cur == nullptr) return;
while(cur->next != nullptr) {
que.push_back(cur->next);
cur = cur->next;
}
cur = head;
int count = 0; // 计数,偶数去后面,奇数取前面
ListNode* node;
while(que.size()) {
if (count % 2 == 0) {
node = que.back();
que.pop_back();
} else {
node = que.front();
que.pop_front();
}
count++;
cur->next = node;
cur = cur->next;
}
cur->next = nullptr; // 注意结尾
}
#141环形链表
constraints真的很重要,看了一眼蛮小的:number of the nodes in the list is [0, 10^4]
就想了个神奇方法,用个数判断:
bool hasCycle(ListNode *head) {
ListNode *cur=head;
int cnt=0;
while(cur){
cnt++;
if(cnt>10000) return true;
cur=cur->next;
}
return false;
}
又写了个用set装的:时间和空间表现都不好
bool hasCycle(ListNode *head) {
set<ListNode *> myset;
ListNode* cur=head;
while(cur){
if(myset.find(cur)==myset.end()) myset.insert(cur);
else return true;
cur=cur->next;
}
return false;
}
随想录方法:快慢指针相遇判断成环(好重要的方法) ,142.环形链表II 这道重要的题就是这样做的,还要用数学计算,我居然忘了
bool hasCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}