LeetCode——数据结构训练(链表十题)

LeetCode——数据结构训练(链表十题)

大部分分类都有了——题号目录网址

对应题号到LeetCode搜索

简单题要理解头结点,头结点是指向节点地址,并没有存放实际内容,主要是方便插入等操作,具体可以百度

160. 找出两个链表的交点(简单题)
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *pA = headA, *pB = headB;
        while(pA!=pB){
            pA = pA!=NULL ? pA->next:headB;
            pB = pB!=NULL ? pB->next:headA;
        }
        return pA;
    }
};
206. 链表反转(简单题)
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* phead = nullptr; // 第一个指向空
        while(head!=nullptr){
            ListNode* next = head->next;
            head->next = phead;
            phead = head;
            head = next;
        }
        return phead;
    }
};
21. 归并两个有序的链表(简单题)
// 大部分简单题都有递归的方法,可以去参考官方代码
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* newHead = new ListNode(-1);
        ListNode* pre = newHead;
        while(l1!=nullptr && l2!=nullptr){
            if(l1->val<l2->val){
                pre->next = l1;
                pre = pre->next;
                l1 = l1->next;
            }
            else{
                pre->next = l2;
                pre = pre->next;
                l2 = l2->next;
            }
        }
        pre->next = l1!=nullptr?l1:l2;
        return newHead->next;
    }
};
83. 从有序链表中删除重复节点(简单题)
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(!head){
            return head;
        }
        ListNode* l1 = head;
        while(l1->next){
            if(l1->val==l1->next->val){
                l1->next = l1->next->next;
            }
            else{
                l1 = l1->next;
            }
        }
        return head;
    }
};
19. 删除链表的倒数第 N 个结点(中等题)
// 一次循环解决,双指针的想法
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* first = head;
        ListNode* last = head;
        while(n--){
            first = first->next;
        }
        // 判断是否删除第一个元素,即只有一个元素
        if(first){
            ListNode* pre = last;
            while(first){
                pre = last;
                first = first->next;
                last = last->next;
            }
            pre->next = last->next;
            delete last;
        }
        else{
            ListNode* q = head;
            head = q->next;
            delete q;
        }
        return head;
    }
};
24. 交换链表中的相邻结点(中等题)
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* one = dummyHead;
        while (one->next != nullptr && one->next->next != nullptr) {
            // one two three 分别代表三个节点,two和three互相交换
            ListNode* two = one->next;
            ListNode* three = one->next->next;
            one->next = three;
            two->next = three->next;
            three->next = two;
            one = two;
        }
        return dummyHead->next;
    }
};
445. 链表求和表(中等题)

不反转链表的方法,官网感觉比较绕
下面是用栈来实现

// 如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> s1,s2;
        while(l1){
            s1.push(l1->val);
            l1 = l1->next;
        }
        while(l2){
            s2.push(l2->val);
            l2 = l2->next;
        }

        ListNode* res = nullptr;
        int carry = 0;
        while(!s1.empty() || !s2.empty() || carry!=0){
            int sum = (s1.empty()?0:s1.top()) + (s2.empty()?0:s2.top()) + carry;
            if(!s1.empty()) s1.pop();
            if(!s2.empty()) s2.pop();
            carry = sum/10;
            ListNode* node = new ListNode(sum%10);
            node->next = res;
            res = node;
        }
        return res;
    }
};
234. 回文链表(简单题)
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == nullptr) {
            return true;
        }

        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode* firstHalfEnd = endOfFirstHalf(head);
        ListNode* secondHalfStart = reverseList(firstHalfEnd->next);

        // 判断是否回文
        ListNode* p1 = head;
        ListNode* p2 = secondHalfStart;
        bool result = true;
        while (result && p2 != nullptr) {
            if (p1->val != p2->val) {
                result = false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }        

        // 还原链表并返回结果
        firstHalfEnd->next = reverseList(secondHalfStart);
        return result;
    }

    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr != nullptr) {
            ListNode* nextTemp = curr->next;
            curr->next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    ListNode* endOfFirstHalf(ListNode* head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast->next != nullptr && fast->next->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
};
725. 分隔链表(中等题)
class Solution {
public:
    vector<ListNode*> splitListToParts(ListNode* root, int k) {
        ListNode* curr = root;
        // 计算长度
        int n = 0;
        while (curr != nullptr)
        {
            curr = curr->next;
            ++n;
        }

        // 长度和余数
        int len = n / k;
        int mod = n % k;

        vector<ListNode*> res(k, nullptr);
        // 重置curr为root起点
        curr = root;
        for (int i = 0; i < k; ++i)
        {
            ListNode* head = curr;
            // 有余数情况,保证前面每个分组多1,所以i<mod
            // 也可以通过mod--来实现
            // int currLen = len + ((i < mod) ? 1 : 0);
            int currLen = len + (mod-->0 ? 1 : 0);
            // 遍历去构建走到当前链表的尾部
            for (int j = 0; j < currLen - 1; ++j)
            {
                if (curr != nullptr)
                {
                    curr = curr->next;
                }
            }
            // 额外去设置curr->next = nullptr
            if (curr != nullptr)
            {
                ListNode* temp = curr;
                curr = temp->next;
                temp->next = nullptr;
            }
            // cout << i << " " << ((head != nullptr) ? head->val : -1) << endl;
            res[i] = head;
        }

        return res;
    }
};
328. 奇偶链表(中等题)
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if(head == nullptr ||head->next==nullptr || head->next->next==nullptr) return head;
        ListNode* odd = head;
        ListNode* even = head->next;
        ListNode* evenhead = even;
        while(even!=nullptr && even->next!=nullptr){
            odd->next = even->next;
            odd = odd->next;
            even->next = odd->next;
            even = even->next;
        }
        odd->next = evenhead;
        return head;
    }
};
2.总结

链表的数据结构,主要理解头指针,把基本头插法这些搞定,题目大部分都还好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值