142.环形链表②
(一开始没反应过来总是觉得两者总是在环入口处相遇,没有将fast=fast->next)
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (head == NULL || head->next == NULL) {return NULL;}
ListNode* slow = head;
ListNode* fast = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
ListNode* p = head;
while (p != fast) { p = p->next;fast=fast->next; }
return p;
}
}
return NULL;
}
(hash表会更简单以后更新)
19. 删除链表的倒数第N个节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode*p=head,*s=head;
int len=0,i=0;
while(p){p=p->next;len++;}
if(len==n){head=head->next;return head;}//用哑结点的话就不需要判断这个了
while(i<len-n-1){
s=s->next;
i++;
}
auto tmp=s->next;
s->next=s->next->next;
delete tmp;
return head;
}
方二:一趟扫描的方法,双指针
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode*dummy=new ListNode(0);
dummy->next=head;
ListNode*first=dummy;
ListNode*sec=dummy;
for(int i=0;i<n+1;i++)
{
first=first->next;
}
while(first)
{
first=first->next;
sec=sec->next;
}
sec->next=sec->next->next;
return dummy->next;
}
328. 奇偶链表
lass Solution {
public:
ListNode* oddEvenList(ListNode* head) {
ListNode*odd=head;
if(head==nullptr||head->next==nullptr)return head;
ListNode*even=head->next;
ListNode* headeven=even;
while(odd->next&&odd->next->next){
odd->next=odd->next->next;
odd=odd->next;
even->next=even->next->next;
even=even->next;;
}
odd->next=headeven;
return head;
}
234. 回文链表
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode*p=head;
ListNode*q=head;
int len=0;
while(p){p=p->next;len++;}
if(len==1)return true;
if(len==2){
if(head->val==head->next->val)return true;
else return false;
}
int index=len/2;
int i=1;
while(q&&i<=index){
q=q->next;
i++;
}//这里也可以使用快慢指针,快指针到结尾慢指针刚好到终点
ListNode*pre=NULL;
while(q)
{
auto tmp=q->next;
q->next=pre;
pre=q;
q=tmp;
}
ListNode*p1=head;
ListNode*p2=pre;
while(p1&&p2)
{
if(p1->val!=p2->val)return false;
p1=p1->next;
p2=p2->next;
}
return true;
}
这个题解写的清楚一点点
class Solution {
public:
//题解:快慢指针法,快指针走两步,慢指针走一步,找到链表的中点。然后,翻转后半部分。最后从头、中点开始判断是否相同。
bool isPalindrome(ListNode* head) {
if(!head||!head->next)return true;
ListNode *fast=head,*slow=head,*pre=nullptr;
//1、找到链表的中点,链表长度奇偶不影响
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
}
//2、将slow之后链表进行断开且反转,最后翻转完成之后pre指向反转链表的头节点
while(slow){
ListNode *p=slow->next;
slow->next=pre;
pre=slow;
slow=p;
}
//3、前后链表进行比较,注意若为奇数链表,后半部分回比前部分多1一个节点,然而我们只比较相同长度的节点值,巧妙地避开这点判断
while(head&&pre){
if(head->val!=pre->val)return false;
head=head->next;
pre=pre->next;
}
return true;
}
};
21. 合并两个有序链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode*dummy=new ListNode(-1);
ListNode*p=dummy;
while(l1&&l2){
if(l1->val<=l2->val)
{
p->next=l1;l1=l1->next;p=p->next;
}
else {p->next=l2;l2=l2->next;p=p->next;}
}
p->next=(l1==nullptr)?l2:l1;
return dummy->next;
}
时间复杂度:O(n+m)
空间复杂度:O(1) 。
方二:递归递归递归!!
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==nullptr) return l2;
else if(l2==nullptr) return l1;
else if(l1->val<l2->val){l1->next=mergeTwoLists(l1->next,l2);return l1; }
else {l2->next=mergeTwoLists(l1,l2->next);return l2;}
}
时间复杂度:O(n+m),其中 n 和 m 分别为两个链表的长度。因为每次调用递归都会去掉 l1 或者 l2 的头节点(直到至少有一个链表为空),函数 mergeTwoList 至多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,即 O(n+m)。
空间复杂度:O(n+m),其中 n 和 m 分别为两个链表的长度。递归调用 mergeTwoLists 函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 mergeTwoLists 函数最多调用 n+m 次,因此空间复杂度为O(n+m)。
61. 旋转链表
还是不知道自己错在哪里,就是一直提示有空指针,十分暴躁以后再调
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
ListNode*p=head;
ListNode*q=head;
if(head==NULL||head->next==NULL)return head;
int len=0,i=0;
while(p){p=p->next;len++;}
k=k%len;
if(k==0)return head;
while(q&&i<len-k){ q=q->next; }
ListNode* m=q->next;
q->next=NULL;
m->next=head;
return m;
}