zoukankan      html  css  js  c++  java
  • LeetCode 初级算法 链表

     1.  删除链表中的节点

      

    请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

    现有一个链表 -- head = [4,5,1,9],它可以表示为:

     

    示例 1:

    输入: head = [4,5,1,9], node = 5
    输出: [4,1,9]
    解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
     
    A: 
    这种初级题目就很简单了,将目标节点的val和next指向next的next就行
        void deleteNode(ListNode* node) {
        ListNode* next_node = node->next;
        node->val = next_node->val;
        node->next = next_node->next;
        }

     

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

      

    给定一个链表,删除链表的倒数第 个节点,并且返回链表的头结点。

    示例:

    给定一个链表: 1->2->3->4->5, 和 n = 2.
    
    当删除了倒数第二个节点后,链表变为 1->2->3->5.
    

    说明:

    给定的 n 保证是有效的。

    进阶:

    你能尝试使用一趟扫描实现吗?

    A:

    方法1:遍历一次链表后,将所有的node存在一个list中,再删除list中指定的映射到原链表的node,可是这样会比较费时和费空间

    ListNode* removeNthFromEnd(ListNode* head, int n) {
            
        vector<ListNode*> vec;
        ListNode* next = head->next;
        while (next) {
            vec.push_back(next);
            next = next->next;
        }
    
        next = vec[vec.size() - n];
        next->val = next->next->val;
        next->next = next->next->next;
    
        return head;   
        
    }

    方法2:更快的办法应该使用快慢指针,即两个指针每次的步长一个大一个小

    在本题中,先让快指针先走N步,再让慢指针和快指针一起走

        ListNode* removeNthFromEnd(ListNode* head, int n) {
        if (head == NULL)
            return NULL;
        ListNode* fast = head;//快指针
        ListNode* slow = head;//慢指针
        //快指针提前移动n次
        for (int i = 0; i < n; i++) {
            fast = fast->next;
        }
        //删除的是链表头部
        if (fast == NULL) {
            return head->next;
        }
        //同时移动快慢指针,直到快指针到链表末尾
        //说明慢指针在要删除的位置上
        while (fast->next != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return head;
        }

     3.  反转链表

    反转一个单链表。

    示例:

    输入: 1->2->3->4->5->NULL
    输出: 5->4->3->2->1->NULL

    进阶:
    你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

    A:

    就单纯个的反转链表

    两种方法的效率都不错

        ListNode* reverseList(ListNode* head) {
        if (head == NULL || head->next == NULL){
            return head;
        }
        else    {
            ListNode* newNode = reverseList(head->next);
            head->next->next = head;
            head->next = NULL;
            return newNode;
        }
        }
        ListNode* reverseList(ListNode* head) {
        ListNode* ret = NULL;
    
        while (head)    {
            ListNode* tmp = head->next;
            head->next = ret;
            ret = head;
            head = tmp;
        }
        return ret;
        }

    4.  合并两个有序链表

    将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

    示例:

    输入:1->2->4, 1->3->4
    输出:1->1->2->3->4->4

    A:
    也就是单纯的合并链表了
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        struct ListNode* head = new ListNode(1);
        struct ListNode* now = head;
        while (l1 != NULL && l2 != NULL) {
            if (l1->val <= l2->val) {
                now->next = l1;
                l1 = l1->next;
            }
            else {
                now->next = l2;
                l2 = l2->next;
            }
            now = now->next;
        }
        if (l1 != NULL) {
            now->next = l1;
        }
        if (l2 != NULL) {
            now->next = l2;
        }
        return head->next;
    }
    
    
    

    5  回文链表

    请判断一个链表是否为回文链表。

    示例 1:

    输入: 1->2
    输出: false

    示例 2:

    输入: 1->2->2->1
    输出: true
    

    进阶:
    你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

    A:

    利用快慢指针,找到整个链表的中点,然后反转后半段,再用前半段和后半段对比

    bool isPalindrome(ListNode* head) {
        if (head == NULL || head->next == NULL)
            return true;
    
        /*    stack<int> first_half;*/
        ListNode* one = head;
        ListNode* two = head;
        /*    first_half.push(one->val);*/
        while (one->next != NULL && two->next != NULL && two->next->next != NULL) {
            one = one->next;
            two = two->next->next;
            /*        first_half.push(one->val);*/
        }
        if (two->next != NULL) {
            one = one->next;
        }
        ListNode* ref = NULL;
        ListNode* helf = one;
        while (one != NULL) {
            ListNode* tmp = one->next;
            one->next = ref;
            ref = one;
            one = tmp;
        }
        ListNode* p = head;
        while (ref != NULL) {
            if (ref->val != p->val) {
                return false;
            }
            ref = ref->next;
            p = p->next;
        }
        return true;
    }

    方法2,利用栈先进后出的原理,再找前半段的同时将val push到stack中,再在遍历后半部分的时候将链表和stack对比

    bool isPalindrome(ListNode* head) {
        if (head == NULL || head->next == NULL)
            return true;
    
        stack<int> first_half;
        ListNode* one = head;
        ListNode* two = head;
        first_half.push(one->val);
        while (one->next != NULL && two->next != NULL && two->next->next != NULL) {
            one = one->next;
            two = two->next->next;
            first_half.push(one->val);
        }
      //
    if (two->next != NULL) { one = one->next; } while (one != NULL) { if (one->val != first_half.top()) { return false; } first_half.pop(); one = one->next; } return true; }

    6  环形链表

    给定一个链表,判断链表中是否有环。

    为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

    示例 1:

    输入:head = [3,2,0,-4], pos = 1
    输出:true
    解释:链表中有一个环,其尾部连接到第二个节点。

    A:

    题目有点拗口,总是就是判断node是不是有环

    同样是利用快慢指针,步长位1和2,只要是个环,快慢指针肯定会某一处相等

        bool hasCycle(ListNode *head) {
        ListNode* one = head;
        ListNode* two = head;
    
        while (two != NULL && two->next != NULL)    {
            one = one->next;
            two = two->next->next;
            if (one == two){
                return true;
            }
        }
        return false;
        }
     
  • 相关阅读:
    最长公共子序列
    字符串循环左移
    收集雨水问题
    直方图最大矩阵面积
    逆波兰表达式
    最长括号匹配问题
    机器学习中用来防止过拟合的方法有哪些?
    制作coco数据集以在Detectron框架上进行数据的训练
    关于训练集,验证集,测试集的划分
    配置CUDA和cuDNN以及Detectron过程
  • 原文地址:https://www.cnblogs.com/gongkiro/p/12716221.html
Copyright © 2011-2022 走看看