C++链表 (刷题lettcode)

持续更新中!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

以下代码中只是应付面试时手撕代码时:输入需要自己创造输入,链表结构体也需要自己创造

leetcode中只需要class Solution部分

部分来源:代码随想录  ,LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

链表理论:

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域,一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

链表的入口节点称为链表的头结点也就是head。

分为单链表,双链表,循环链表:

双链表:

双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点

              既可以向前查询也可以向后查询

循环链表:

        循环链表:就是链表首尾相连

链表是通过指针域的指针链接在内存中各个节点。

所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

移除链表元素:

203. 移除链表元素 - 力扣(LeetCode)

以下只是应付面试时手撕代码时:输入需要自己创造输入,链表结构体也需要自己创造

leetcode中只需要class Solution部分

#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

class Solution
{
public:
    ListNode* removeElements(ListNode*head,int val){
        if(head==nullptr) return head;
        ListNode* dummy_node = new ListNode(0);
        dummy_node->next = head;

        ListNode* cur_node = dummy_node;
        while(cur_node->next!=nullptr)
        {
            if(cur_node->next->val == val)
            {
                ListNode* tmp = cur_node->next;
                cur_node->next = cur_node->next->next;
                delete tmp;
            }else{
                cur_node = cur_node->next;
            }

        }
        
        head = dummy_node->next;
        delete dummy_node;
        return head;

    }
};

 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(4);
     head->next->next->next->next->next = new ListNode(5);
     head->next->next->next->next->next->next = new ListNode(6);
    
     Solution s;
     // ListNode* ListNode;
     ListNode* cur_head = s.removeElements(head,6);
     while(cur_head!=nullptr)
     {
         std::cout<<cur_head->val;
         cur_head = cur_head->next;
     }
     return 0;

 }

反转链表:

206. 反转链表 - 力扣(LeetCode)

#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            ListNode* prev = nullptr;
            ListNode* cur_node = head;
            ListNode* temp;
            while(cur_node != nullptr)
            {
                temp = cur_node->next;
                cur_node->next = prev;

                //更新pre和cur
                prev = cur_node;
                cur_node = temp;
            }

            return prev;
            
        }
    };

 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(4);
     head->next->next->next->next->next = new ListNode(5);
     head->next->next->next->next->next->next = new ListNode(6);
    
     Solution s;
     // ListNode* ListNode;
     ListNode* cur_head = s.reverseList(head);
     while(cur_head!=nullptr)
     {
         std::cout<<cur_head->val;
         cur_head = cur_head->next;
     }
     return 0;

 }

两两交换链表:

24. 两两交换链表中的节点 - 力扣(LeetCode)

#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 class Solution {
    public:
        ListNode* swapPairs(ListNode* head) {
            ListNode* dummynode = new ListNode(0);
            dummynode->next = head;
            ListNode* cur = dummynode;
            
            while(cur->next != nullptr && cur->next->next!=nullptr) {   //顺序不能返
                ListNode* temp1 = cur->next;
                ListNode* temp2 = cur->next->next->next;

                cur->next = cur->next->next;
                cur->next->next = temp1;
                cur->next->next->next = temp2;

                cur = cur->next->next;   //移动两位下一轮
                
            }
            ListNode* result = dummynode->next;
            delete dummynode;
            return result;

            
        }
    };



 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(4);
     head->next->next->next->next->next = new ListNode(5);
     head->next->next->next->next->next->next = new ListNode(6);
    
     Solution s;
     // ListNode* ListNode;
     ListNode* cur_head = s.swapPairs(head);
     while(cur_head!=nullptr)
     {
         std::cout<<cur_head->val;
         cur_head = cur_head->next;
     }
     return 0;

 }

删除链表的倒数第N个节点:

#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode* dummy = new ListNode(0);
            dummy->next = head;
            ListNode* fast = dummy;
            ListNode* slow = dummy;
            while(n-- && fast!=nullptr)
            {
                fast = fast->next;
            }

            fast = fast->next;   //同时移动slow指针和fast时  保持在删除节点的上个位置 

            while(fast!=nullptr)
            {
                fast = fast->next;
                slow = slow->next;
            }
            slow->next = slow->next->next;

            return dummy->next;
            
            
        }
    };



 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(4);
     head->next->next->next->next->next = new ListNode(5);
     head->next->next->next->next->next->next = new ListNode(6);
    
     Solution s;
     // ListNode* ListNode;
     ListNode* cur_head = s.removeNthFromEnd(head,1);
     while(cur_head!=nullptr)
     {
         std::cout<<cur_head->val;
         cur_head = cur_head->next;
     }
     return 0;

 }

相交链表:

  • 通过双指针遍历,分别走完两条链表的总长度,使得指针在相交点处相遇。
  • 如果没有相交,最终 pq 会同时到 nullptr,返回 nullptr
  • 时间复杂度 O(m + n),空间复杂度 O(1),是寻找相交节点的最优解法之一。

#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 //移动的距离相等时
 class Solution {
    public:
        ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {

            ListNode* p = headA;
            ListNode* q = headB;
            // 若A,B无交点,返回nullptr
            //有交点返回  他们走的距离
            while(p!=q)
            {
                p = p ? p->next : headB;
                q = q? q->next : headA;
            }

            return p;
            
        }
    };



 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(4);
     head->next->next->next->next->next = new ListNode(5);
     head->next->next->next->next->next->next = new ListNode(6);
     
     //错误 这里 head 和 headB 各自独立,它们的 ListNode 互不影响,没有真正共享的节点
//
//     ListNode* headB = new ListNode(2);
//     headB->next = new ListNode(6);
//     headB->next->next = new ListNode(3);
//     headB->next->next->next = new ListNode(4);
//     headB->next->next->next->next = new ListNode(5);
//     headB->next->next->next->next->next = new ListNode(6);
	
	//赋值情形一
	 ListNode* headB = new ListNode(3);
     headB->next = new ListNode(6);
     //以下才开始相交
     headB->next->next = head->next->next->next;
     headB->next->next->next = head->next->next->next->next;
     headB->next->next->next->next = head->next->next->next->next->next;
     headB->next->next->next->next->next = head->next->next->next->next->next->next;
		
    //直接赋值相交点--赋值情形二
//    ListNode* headB = head->next;  
     Solution s;
     // ListNode* ListNode;
     ListNode* cur_head = s.getIntersectionNode(head,headB);
     while(cur_head!=nullptr)
     {
         std::cout<<cur_head->val<<" ";
         cur_head = cur_head->next;
     }
     return 0;

 }

环形链表:

利用双指针:快指针与慢指针

代码随想录

  • while(fast != NULL && fast->next != NULL):这部分检查快指针和慢指针是否会碰撞,如果快指针或者快指针的下一个指针为 NULL,则说明链表无环,直接返回 NULL
  • ListNode* meet = head; while(meet != slow):找到环的入口节点。slowmeet 从链表头部同时出发,每次向前走一步,直到它们相遇,即为环的入口节点。

142. 环形链表 II - 力扣(LeetCode)


#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 class Solution {
    public:
        ListNode *detectCycle(ListNode *head) {
            ListNode* fast = head;
            ListNode* slow = head;

            while(fast!=NULL && fast->next!=NULL)
            {
                slow = slow->next;
                fast = fast->next->next;
                if(slow==fast)
                {
                    //找到入口点
                    ListNode* meet = head;
                    while(meet!=slow)
                    {
                        meet = meet->next;
                        slow = slow->next;
                    }
                    return meet;
                }
            }
            return NULL;
            
        }
    };



 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(4);
     head->next->next->next->next->next = new ListNode(5);
     head->next->next->next->next->next->next = head->next->next;

    //  ListNode* headB = new ListNode(2);
    //  headB->next = new ListNode(6);
    //  headB->next->next = new ListNode(3);
    //  headB->next->next->next = new ListNode(4);
    //  headB->next->next->next->next = new ListNode(5);
    //  headB->next->next->next->next->next = new ListNode(6);
    
     Solution s;
     // ListNode* ListNode;
     ListNode* cur_head = s.detectCycle(head);
//     while(cur_head!=nullptr)
//     {
//         std::cout<<cur_head->val;
//         cur_head = cur_head->next;
//     }
	
	if(cur_head!=NULL)
	{
		std::cout<<cur_head->val;
		
	}
     return 0;

 }

回文链表:

#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 //时间复杂度O(n)和空间复杂度O(1)
 class Solution {
    public:
        bool isPalindrome(ListNode* head) {
            ListNode* slow = head;
            ListNode* fast = head->next;
            while(fast!=NULL && fast->next!=NULL)
            {
                fast = fast->next->next;
                slow = slow->next;
            }

            //当队列为偶数时此时slow已经在链表的分割点中间位置
            //奇数时 slow在中间位置 判断左右两边的链表是否相等

            ListNode* second_head = slow->next;   //第二个列表的头节点
            slow->next = nullptr;  //断开断开的左半部分
            ListNode* pre = nullptr;
            while(second_head!=NULL)
            {
                ListNode* temp = second_head->next;
                second_head->next = pre;
                pre = second_head;
                second_head = temp;
            }

            slow = head;
            //此时pre是second链表中的头节点
            while(pre) //只要pre不为空
            {
                if(pre->val ==slow->val )
                {
                    slow = slow->next;
                    pre = pre->next;
                }
                else{
                    return false; // 不是回文
                }

            }
            return true; // 回文
            
        }


        // //封装reverslist
        // ListNode* reversList(ListNode* head)
        // {
        //     ListNode* pre = nullptr;
        //     ListNode* cur = head;
        //     while(cur!=nullptr)
        //     {
        //         ListNode* temp = cur->next;
        //         cur->next = pre;
        //         pre = cur;
        //         cur = temp;
        //     }
        //     return pre;
        // }
    };


 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(6);
     head->next->next->next = new ListNode(3);
     head->next->next->next->next = new ListNode(6);
     head->next->next->next->next->next = new ListNode(2);
     head->next->next->next->next->next->next = new ListNode(1);

    //  ListNode* headB = new ListNode(2);
    //  headB->next = new ListNode(6);
    //  headB->next->next = new ListNode(3);
    //  headB->next->next->next = new ListNode(4);
    //  headB->next->next->next->next = new ListNode(5);
    //  headB->next->next->next->next->next = new ListNode(6);
    
     Solution s;
     // ListNode* ListNode;
    //  ListNode* cur_head = s.detectCycle(head)
    //  while(cur_head!=nullptr)
    //  {
    //      std::cout<<cur_head->val;
    //      cur_head = cur_head->next;
    //  }

    bool flag = s.isPalindrome(head);
     std::cout<<flag<<std::endl;
     return 0;

 }

合并两个有序链表:

21. 合并两个有序链表 - 力扣(LeetCode)

思想:pre的思想 删除链表的节点类似


#include<iostream>
 struct ListNode
 {
     int val;
     ListNode* next;
     ListNode():val(0),next(nullptr){};
     ListNode(int val):val(val),next(nullptr){};
     ListNode(int val, ListNode* next):val(val), next(next){};

 };

 class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
            if(list1==NULL || list2==NULL)
            {
                if(list1 == NULL) return list2;
                if(list2 == NULL) return list1;
            }
    
            ListNode* head = (list1->val <= list2->val) ? list1 : list2;
            ListNode* pre = head;
            ListNode* cur1 = pre->next;
            ListNode* cur2 = (pre==list1) ? list2 :list1;   //如果当前的pre和当前的head相同 cur2指向下一个节点
            while(cur1!=NULL && cur2!=NULL)
            {
                if(cur1->val <= cur2->val) 
                {
                    pre->next = cur1;
                    cur1 = cur1->next;
                }
                else
                {
                    pre->next = cur2;
                    cur2 = cur2->next;
                }
                pre = pre->next;
            }
    
            pre->next = cur1==NULL? cur2 : cur1;
            return head;
            // if(list1->val <= list2->val)
            // {
            //     ListNode*head = list1;
            // }
            
        }
    };

 int main()
 {
     ListNode* head = new ListNode(1);
     head->next = new ListNode(2);
     head->next->next = new ListNode(4);
     head->next->next->next = new ListNode(6);
     head->next->next->next->next = new ListNode(7);
     head->next->next->next->next->next = new ListNode(9);
     head->next->next->next->next->next->next = new ListNode(9);

     ListNode* headB = new ListNode(2);
     headB->next = new ListNode(3);
     headB->next->next = new ListNode(5);
     headB->next->next->next = new ListNode(6);
     headB->next->next->next->next = new ListNode(7);
     headB->next->next->next->next->next = new ListNode(8);
    
     Solution s;
    //  ListNode* ListNode;
     ListNode* cur_head = s.mergeTwoLists(head,headB);
     while(cur_head!=nullptr)
     {
         std::cout<<cur_head->val;
         cur_head = cur_head->next;
     }
     return 0;

    // bool flag = s.isPalindrome(head)
    //  std::cout<<flag<<std::endl;
    //  return flag;

 }

两数相加:

2. 两数相加 - 力扣(LeetCode)

注意:两个列表长度不同的时候,用val1 ,val2模拟0值 进行计算,进位也同样如此

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        int res ;
        int carry=0;
        ListNode* dummy = new ListNode();   //虚拟头节点至关重要
        ListNode* cur = dummy;
        while(l1!=NULL || l2!=NULL || carry)
        {
            int val1 = 0,val2=0;
            if(l1)
            {
                val1 = l1->val;
                l1 = l1->next;
            }

            if(l2)
            {
                val2 = l2->val;
                l2 = l2->next;
            }

            res = val1 + val2 + carry;
            cur->next = new ListNode(res%10);  //取余数
            carry = res/10;     //取除数
            cur = cur->next;
        }     
        return dummy->next;   
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值