首页 > 其他分享 >经典数据结构题目解析

经典数据结构题目解析

时间:2024-09-06 21:21:09浏览次数:12  
标签:head 解析 ListNode NULL fast next return 题目 数据结构

链表

1.删除单链表的重复节点

遍历法

class Solution {
public:
    ListNode* removeDuplicateNodes(ListNode* head) {
        //先检查头节点是否为空,快速判断
        if (head == NULL) {
            return NULL;
        }  
        ListNode *current = head;
        //循环遍历检查每一个元素,如果有相同元素则去掉
        while (current) {
            ListNode *p = current;
            while (p->next) {
                if (p->next->val == current->val) {
                    ListNode *toDelete = p->next;
                    p->next = p->next->next;
                    delete toDelete; // 释放内存
                } else {
                    p = p->next;
                }
            }
            current = current->next;
        }
        return head;
    }
};

数组法:用一个数组指示,数组初始为0,一次遍历元素的值,出现就将数组对应值置1

2. 如何找出链表的倒数第K个元素

快慢指针法:快指针比慢指针快K个元素,当快指针指向末尾NULL时,此时慢指针指向倒数第K个元素。

class Solution {
public:
    //快慢指针:空间换时间
    ListNode* trainingPlan(ListNode* head, int cnt) {
        ListNode* fast=head;
        ListNode* slow=head;
        while(cnt--)
        {
            fast=fast->next;
        }
        while (fast)
        {
            fast=fast->next;
            slow=slow->next;
        }
        return slow;
    }
};

 3. 如何找出链表的中间节点

双指针:快指针走两步,满指针走一步

class Solution {
public:
    //双指针法
    ListNode* middleNode(ListNode* head) {
        ListNode* fast=head;
        ListNode* slow=head;
        while((fast!=NULL)&&(fast->next!=NULL))
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        return slow;
    }
};

4. 反转链表

反转是逐个反转,例如反转1,2,3,4,5

先变成2,1,3,4,5

再3,2,1,4,5

依次直至最终反转

class Solution {
public:
    //递归实现反转链表
    ListNode* trainningPlan(ListNode* head) {
        if(head==NULL || head->next==NULL){
            return head;
        }
        else
        {
            struct ListNode* mid=head;
            struct ListNode* lateer=mid->next;
            head =trainningPlan(lateer);
            lateer->next=mid;
            mid->next=NULL;
            return head;
        }
    }
};

5.环形链表  

快慢指针:总会相遇,一个两部一个一步

class Solution {
public:
    //快慢指针,追到就是了
    bool hasCycle(ListNode *head) {
        ListNode *fast=head;
        ListNode *slow=head;
        while((fast!=NULL)&&(fast->next!=NULL))
        {
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
                return true;
        }
        return false;
    }
};

6. 单链表相交,如何求交点

移动相同的距离即是交点

class Solution {
public:
    //这不是判断是否相交,比较简单,判断交点则AD+BD+DC
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p=headA;
        ListNode *q=headB;
        while(p!=q)
        {
            if(p!=NULL)
                p=p->next;
            else
                p=headB;

            if(q!=NULL)
                q=q->next;
            else
                q=headA;   
        }
        return q;
    }
};

7. 回文链表

找链表中间位置。将后半链表反转,依次和链表前一部分比较,看是否一致。

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == NULL) return true;
        
        // 找到链表的中间节点
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast != NULL && fast->next != NULL) {
            fast = fast->next->next;
            slow = slow->next;
        }
        
        // 反转链表的后半部分
        ListNode* mid = slow;
        ListNode* prev = NULL;
        while (mid != NULL) {
            ListNode* nextTemp = mid->next;
            mid->next = prev;
            prev = mid;
            mid = nextTemp;
        }
        
        // 将slow指向反转后链表的头节点
        slow = prev;
        
        // 比较前半部分和反转后的后半部分是否相同
        fast = head;
        while (slow != NULL) {
            if (fast->val != slow->val) {
                return false;
            }
            fast = fast->next;
            slow = slow->next;
        }
        return true;
    }
};

8. 算法实现两个有序链表的合并

递归实现,返回两个链表最小值,

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1==NULL)
            return list2;
        if(list2==NULL)
            return list1;
        if(list1->val<list2->val)
        {
            list1->next= mergeTwoLists(list1->next,list2);
            return list1;
        }
        else
        {
            list2->next=mergeTwoLists(list1,list2->next);
            return list2;
        }
    }
};

树代码的核心操作在于递归

1.求二叉树的深度

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int calculateDepth(TreeNode* root) {
        if(root ==NULL)
        {
            return 0;
        }
        int Lenleft=calculateDepth(root->left);
        int lenright=calculateDepth(root->right);
        return Lenleft>lenright?Lenleft+1:lenright+1;
    }
};

2.如何判断二叉树是否相等

class Solution {
public:
    //用某种遍历方法,存储成数组,遍历一棵树后,看数组是否相等
    void preOrder(struct TreeNode *root,int *arr,int *i)
    {
        //用指针变量指示数组值的位置
        (*i)++;
        if(root==NULL)
        {
            *(arr+*i)=0;
            return;
        }
        *(arr+*i)=root->val; 
        preOrder(root->left,arr,i);
        preOrder(root->right,arr,i);
    }
    //前序遍历得到数组,再判断数组是否相等
    bool isSameTree(TreeNode* p, TreeNode* q) {
        int i,j;
        int arr1[1000],arr2[1000];
        memset(arr1,0,1000*sizeof(int));
        memset(arr2,0,1000*sizeof(int));
        if((p==NULL)&&(q==NULL))
            return 1;
        if((p==NULL)||(q==NULL))
            return 0;
        j=i=0;
        preOrder(p,arr1,&i);
        preOrder(q,arr2,&j);
        for(i=0;i<1000;i++)
        {
            if(arr1[i]!=arr2[i])
            {
                return 0;
            }
        }
        return 1;
    }
};

3. 判断二叉树是否是平衡二叉树

挨个判断每个节点是否平衡,核心就是递归;

class Solution 
{
public:
    int deptmax(TreeNode* root)
    {
        if(root==NULL)
        {
            return 0;
        }
        int leftdept=deptmax(root->left);
        int rightdept=deptmax(root->right);
        return leftdept>rightdept?leftdept+1:rightdept+1;
    }
    
    //判断每一个节点的左右子树的深度,如何减少复杂度,实则判断meiyih
    bool isBalanced(TreeNode* root) {
        if(root==NULL)
        {
            return true;
        }
        int leftdept=deptmax(root->left);
        int rightdept=deptmax(root->right);
        if(abs(leftdept-rightdept)<2==false)
        {
            return false;
        }
        return abs(leftdept-rightdept)<2&&isBalanced(root->left)&&isBalanced(root->right);
    }
};

 数组

最大子序和

动态规划小问题,值得一看

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
       int pre=0,maxans=nums[0];
       for(const auto &x:nums)
       {
        pre =max(pre+x,x);
        maxans=max(maxans,pre);
       } 
       return maxans;
    }
};

挨个判断将新元素加入子序列的影响。 

标签:head,解析,ListNode,NULL,fast,next,return,题目,数据结构
From: https://blog.csdn.net/xace007/article/details/141499473

相关文章

  • 【数据结构和算法实践-位运算-找出数组中出现K次的数,其他数出现M次】
    位运算-找出数组中出现K次的数,其他数出现M次题目MyThought代码示例JAVA-8题目一个数组中,一个数出现了K次,另外其他的数出现了M次,找出出现K次的数MyThought一、设置一个长度为32的int[]temp,把arr中的每个数都变成2进制,放入temp中1、设置长度为32的int数组2......
  • SG-SLAM: A Real-Time RGB-D Visual SLAMToward Dynamic Scenes With Semantic andGeo
    目录一、引言二、相关工作A.动态场景中的SLAMB.语义建图三、系统概述A.系统框架B.目标检测C.极线约束D.动态特征剔除策略E.动态特征剔除策略四、实验结果A.基于TUMRGB-D数据集的性能评估B.BonnRGB-D数据集的性能评估 C.动态特征剔除策略的有效性D.时间分析......
  • 数据结构-----栈 、队列
    1.数据结构中的栈和系统栈的区别        数据结构中的栈(Stack)与系统栈在本质上是相似的,都遵循“先进后出”(LastInFirstOut,LIFO)的原则,但它们在应用场景、实现方式和管理方式上存在显著的区别。1.1数据结构中的栈定义与特性:数据结构中的栈是一种特殊的线性表......
  • 如何成为AI产品经理?AI产品经理成长秘籍:关键技能与职业发展路径全解析
    点点说在前面:本篇文章由KingJames来分享关于AI产品经理的必备技能和成长策略。KingJames之前做过AI咨询,对接公司内部AI产品经理,外部对接过很多甲方AI产品经理,也曾手持多家公司AI产品经理的offer。快读完这则诚意满满的大佬干货帖吧!—1—AI产品经理是什么回答这个问......
  • 数据结构与算法 第10天(图的应用)
    一、最小生成树生成树:所有顶点均由边连接在一起,但不存在回路一个图可以有多颗不同的生成树 生成树特点:生成树的顶点个数与图的顶点个数相同;生成树是图的极小连通子图,去掉一条边则非连通,一个有n个顶点的连通图的生成树有n-1条边;在生成树中再加一条边必然形成回路,......
  • 数据结构 栈 队列
    系统栈:保护局部变量函数的形参和返回值函数的调用关系(保护现场,恢复现场操作,遵循先进后出,后进先出)数据结构栈(顺序栈,链式栈):同样遵遵循先进后出,后进先出原则只允许从一端进行数据的插入和删除的线性存储结构数据的插入--->入栈     数据的删除----->出栈顺序栈:......
  • 队列-数据结构
    一、队列FIFO特点:先进先出,后进后出允许从一段插入数据,另一端删除数据的线性存储结构队尾:插入数据入队队头:删除数据出队管道实质上也是一个队列。用途:缓存数据(主要是避免两者速度不匹配的,数据存取速度不匹配。)二、队列类型2.1、顺序队列顺序队列---------》假溢出--......
  • 解析NaiveUiAdmin的vue开源项目(二)
     书接上回 解析NaiveUiAdmin的vue开源项目(一)-CSDN博客本章我们来看until下的包 src/utils/http/axios/Axios.tsimporttype{AxiosRequestConfig,AxiosInstance,AxiosResponse}from'axios';importaxiosfrom'axios';import{AxiosCanceler}from'./axio......
  • 深入解析CJS与MJS的差异:模块化编程中的两种主流模式比较
    在现代JaScript开发中,模块化编程已成为构建复杂应用的重要方式。常见的模块化标准有两种:CommonJS(CJS)和ESModule(MJS)。这两者在本质上虽然都是为了解决模块化问题,但在实现方式、使用场景等方面存在显著差异。本文将深入解析CJS与MJS的差异,帮助大家更好地理解它们的特点及在实际开发......
  • 直播美颜SDK与主播美颜工具:实时美颜技术的深度解析
    本篇文章,笔者将深入解析直播美颜SDK的核心技术与主播美颜工具的开发原理。 一、什么是直播美颜SDK?通过集成美颜SDK,开发者可以在直播应用中快速实现脸部优化、滤镜添加、皮肤调整等功能,帮助主播在直播过程中实时呈现最佳状态。不同于传统的后期处理,直播美颜SDK依靠强大的实时处理能......