图灵日记之Leetcode删除有序数组中的重复项&&合并两个有序数组&&移除链表元素

这篇具有很好参考价值的文章主要介绍了图灵日记之Leetcode删除有序数组中的重复项&&合并两个有序数组&&移除链表元素。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

删除有序数组中的重复项

题目入口

题目内容

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。

节选部分内容,建议看原题

思路

这种思路我之前也讲过讲过类似的双指针问题,这里指针不是真指针,而是表示数组下标的一种形象的说法

一般来说,我们要先分成两个数组模拟来思考思路的,但是本题要是先分两个数组来考虑,要用到三指针,所以再试着思考一下下一步的步骤复杂度,下一步我们是要在原数组进行思考,我们还是设立两个指针,一个叫big,另一个叫small(本人习惯,big是大哥,small是小弟).

big负责遍历数组,不对原数组进行干涉
small负责修改数组

不想好一个遍历的指针在后面判断跳出循环容易搞混的

过程就是在big指针遍历的过程中,判断small与big各自指向的元素是否相同,因为我们要找不重复的元素,所以当small和big指向的元素不相同的时候,我们要先++small,因为你不加加,small最开始指向的是第一个元素会被覆盖,所以要先++small覆盖数组第二个位置(原题的nums[1])

代码

big指针用来遍历,在代码中初始值应该是0,但是因为small和big都是第一个位置肯定相等,big++为1,这里就直接上来赋值1,也可以在思路上从第二个位置考虑,都行,这里提醒一下

c版本

int removeDuplicates(int* nums, int numsSize) 
{
       int big = 1;
       int small = 0;
       while(big<numsSize)
       {
           if(nums[big]!=nums[small])
           nums[++small] = nums[big];
           big++;
       } 
       return small+1;
}

c嘎嘎版本

class Solution {
public:
    int removeDuplicates(vector<int>& nums) 
    {
        int big = 1;
        int small = 0;
        while(big<nums.size())
        {
            if(nums[big]!=nums[small])
            {
                nums[++small] = nums[big];
            }
            big++;
        }
        return small+1;
    }
};

合并两个有序数组

题目链接

题目内容

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

思路

最终排序的有序数组要在nums1中进行,本题我们采用从后往前的对两个数组进行遍历挑选,采用从前往后的思路是要挪动数据的,时间复杂度就上来了,而且麻烦,所有我们不妨换种思路,从后往前来考虑
我们从后往前考虑要注意对两个数组边界进行考虑,无非是nums1数组有效元素遍历完或者nums2有效元素遍历完
第一种情况:nums1有效元素遍历完,nums2仍然有剩余元素,所以我们继续从后往前在nums1数组进行覆盖即可
第一个数组指向的动态下标我们叫end1,第二个叫end2,在end1后面是我们处理过的元素,end1前面是未处理的元素,又因为本身数组的有序,所以在我们遍历完后,即便end2的数据覆盖完,end1没走到0位置,也是非递减排序
第二种情况:nums2遍历完,我刚才说过两个数组都是有序数组,所以在nums2遍历之后nums1已经是非递减状态,可以自己尝试画图看一下

代码

c版本(c嘎嘎版本与c版本内容一样)

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 
{
    int end1 = m-1;
    int end2 = n-1;
    int num = m+n-1;
    while(end1>=0&&end2>=0)
    {
        if(nums2[end2]>nums1[end1])
        {
            nums1[num] = nums2[end2];
            num--;
            end2--;
        }
        else
        {
            nums1[num] = nums1[end1];
            num--;
            end1--;
        }
    } 
    while(end2>=0)
    {
            nums1[num] = nums2[end2];
            num--;
            end2--;
    }
}

移除链表元素

题目链接

题目内容

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

思路1

第一种思路就是最直接的思路删除,而单链表的删除要记得站在本节点的上一个才能对本节点进行删除,所以我们要处理两个问题,第一个要在针对节点时分情况讨论头节点和其他节点的问题,第二个我前面提过要站在节点前面才能对本节点进行修改所以我们要使用两个动态指针来标记前一个节点和该节点

代码1

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode*  big=head,*small=NULL;
    //big还是本人习惯的方式,大哥指针,用来
    //遍历链表,small就是小弟指针,用来记录前一个
    //节点的地址
    while(big)
    {
    //第一层判断就是判断big指针里的数值
    //是不是所要删除的数值
    //如果是的就进行删除操作
    //不是的话就跳进下一个
        if(big->val==val)
        {
        //第二层循环判断头节点等于删除数值的情况
        //如果是头节点是删除数值会直接跳入这个
        //循环,不会让small小弟指针记录
        //当然,头节点也没有前节点,所以就要
        //特殊考虑
            if(small==NULL)
            {
            //head头节点是删除数据的情况下
            //你还要更新头节点,让头节点
            //指向下一个节点
            //此处可以解决一直出现删除数据的
            //情况,比如你要删除1,然后数据给的
            //是1 1 1 2,这个代码可以一直把头节点
            //更新到第一个头节点非删除值得情况
                big = head->next;
                free(head);
                head=big;
            }
            else 
            {
            //删除操作
                small->next = big->next;
                free(big);
                big=small->next;
            }
        }
        else 
        {
            small=big;
            big=big->next;
        }
    }
    return head;
}   

思路2

链表删除

使用tail指针来遍历链表
tail判断是不是删除的对应数值,如果是就跳过,如果不是就把next指针指向他,并跳到下一个节点
newnode作为新链表(删除后的链表)
newnode赋值的是head的地址,刚开始newnode指向的就是原链表,为了方便理解,所以我把在录视频的时候分成两个部分来更好的理解这个思路

代码2

struct ListNode* removeElements(struct ListNode* head, int val) 
{
       struct ListNode* newnode=NULL,* tail=NULL;
       while(head!=NULL)
       {
            if(head->val==val)
            {
            /*
			当节点指向的是被删除的对象时,就要跳过这个节点,指向下一个节点来达到删除的目的
			*/
                head=head->next;
            }
            else 
            {
            /*
			在链表不是空链表时,对newnode初始化,指向原链表
			*/
                if(newnode==NULL)
                {
                    newnode=head;
                    tail=newnode;
                }
                else 
                {
                /*
                在head指向不是删除元素的时候,
                用tail进行连接该节点,并跳到下一个
                节点          
                */
                    tail->next=head;
                    tail=tail->next;
                }
                /*
                head指向下一个节点
                tail的next指针要置为空,因为这个思路是让newnode指向新链表新的头节点,利用tail不断向后遍历链表来连接非删除值得节点,而你tail最后一个不置为NULL,那么在调用该函数得时候,无法判断该链表的结束节点,tail->next最后一次变成野指针
                */
                head=head->next;
                tail->next=NULL;
            }
       }
       head=newnode;
       return head;
}

思路3

第三种思路与第一种思路类似,是先对头节点的情况来讨论,然后让头节点是一个非删除值的节点,然后进行正常的删除操作文章来源地址https://www.toymoban.com/news/detail-765407.html

代码3

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val) 
{
//判断是不是空链表
    if(head==NULL) return head;
    //非空链表解决一连串的删除值头节点的情况
    while(head->next!=NULL&&head->val==val)
    {
        head=head->next;
    }
    //看看在删除完一连串删除值头节点的情况下,
    //是否是空链表
    if(head->next==NULL&&head->val==val)
    return NULL;
    //头节点非删除值的节点,开始正常的删除操作
    struct ListNode* p = head;
    while(p->next)
    {
        if(p->next->val==val)
        {
            struct ListNode* tem = p->next;
            p->next = tem->next;
            free(tem);
        }
        else
        {
            p = p->next;
        }
    }
    return head; 
}

到了这里,关于图灵日记之Leetcode删除有序数组中的重复项&&合并两个有序数组&&移除链表元素的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LeetCode刷题集(三)(26 删除有序数组中的重复项)

    基本掌握LeetCode中的26删除有序数组中的重复项 题目描述: 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。 由于在某些语言中不能改变数组的长度,所以必须将结果放

    2023年04月17日
    浏览(28)
  • 【每日一题】2.LeetCode——删除有序数组中的重复项

    📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有限,欢迎各位大佬指点,相互学习进步! 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元

    2024年02月19日
    浏览(36)
  • 【Leetcode -21.合并两个有序链表 -83.删除排序链表中的重复元素】

    题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 = [1, 2, 4], l2 = [1, 3, 4] 输出:[1, 1, 2, 3, 4, 4] 示例 2: 输入:l1 = [], l2 = [] 输出:[] 示例 3: 输入:l1 = [], l2 = [0] 输出:[0] 我们的思路是,先定义

    2023年04月24日
    浏览(34)
  • leetcode做题笔记80删除有序数组中的重复项 II

    给你一个有序数组  nums  ,请你  原地  删除重复出现的元素,使得出现次数超过两次的元素 只出现两次  ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在  原地 修改输入数组  并在使用 O(1) 额外空间的条件下完成。 说明: 为什么返回数值是整数,但输

    2024年02月12日
    浏览(35)
  • LeetCode80. 删除有序数组中的重复项 II(JavaScript版)

    LeetCode题目链接 题目描述:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 js版本

    2024年02月06日
    浏览(25)
  • 用Rust刷LeetCode之26 删除有序数组中的重复项

    26. 删除排序数组中的重复项 [1] 难度: 简单 老的描述: 新的描述: 注意是 排序数组 , 非严格递增排列 ,即已经是排好序的,只不过有重复元素 Rust版本: remove_duplicates 函数使用双指针的方法来原地删除重复元素。指针 i 指向当前已处理的非重复元素的最后一个位置,指针 j 用于遍

    2024年02月04日
    浏览(27)
  • 算法leetcode|80. 删除有序数组中的重复项 II(rust重拳出击)

    给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 说明 : 为什么返回数值是整数,但输出的答案是

    2024年02月09日
    浏览(37)
  • LeetCode-Java:26.删除有序数组的重复项

    给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过

    2024年02月05日
    浏览(36)
  • 26. 删除有序数组中的重复项

    给你一个  升序排列  的数组  nums  ,请你  原地  删除重复出现的元素,使每个元素  只出现一次  ,返回删除后数组的新长度。元素的  相对顺序  应该保持  一致  。然后返回  nums  中唯一元素的个数。 考虑  nums  的唯一元素的数量为  k  ,你需要做以下事情确保

    2024年02月17日
    浏览(37)
  • 115.删除有序数组中的重复项 removeDuplicatesFromSortedArray

    题目链接 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通

    2024年02月06日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包