首页 > 其他分享 >数据结构之线性表——LeetCode:80. 删除有序数组中的重复项 II,88. 合并两个有序数组,4. 寻找两个正序数组的中位数

数据结构之线性表——LeetCode:80. 删除有序数组中的重复项 II,88. 合并两个有序数组,4. 寻找两个正序数组的中位数

时间:2024-09-22 21:49:09浏览次数:3  
标签:数组 nums 元素 len 有序 nums1 nums2 线性表

80. 删除有序数组中的重复项 II

题目描述

80. 删除有序数组中的重复项 II

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

运行代码

class Solution {
public:
int work(vector<int>& nums,int k){
    int len =0;
    for(auto num:nums)
    if(len <k||nums[len-k]!=num)
    nums[len++]=num;
    return len;
}
    int removeDuplicates(vector<int>& nums) {
return work(nums,2);
    }
};

代码思路

  1. 定义了一个类 Solution,其中包含两个函数 work 和 removeDuplicates
    • removeDuplicates 函数是对外提供的接口,它调用了 work 函数来实现具体的逻辑。
    • work 函数实现了删除有序数组中重复项的功能,使得重复项最多出现 k 次(在本题中 k = 2)。
  2. removeDuplicates 函数:作用是调用 work 函数并传入参数 2,表示要将重复项控制在最多出现两次。最后返回处理后的数组长度。

  3. work 函数:

    • 接收两个参数,一个是整数向量 nums,另一个是整数 k,表示重复项最多出现的次数。
    • 初始化变量 len 为 0,这个变量用于记录处理后的数组长度。
    • 通过遍历输入的 nums 数组中的每个元素 num
      • 如果 len < k,说明当前元素无论如何都应该被保留,因为还没有达到重复项出现的最大次数。
      • 如果 nums[len - k]!= num,说明距离当前位置 k 个位置之前的元素与当前元素不同,即当前元素不是重复项或者重复次数还未达到 k,也应该被保留。
      • 当满足上述条件之一时,将当前元素 num 赋值给 nums[len],并将 len 加一,实现将不重复或重复次数未达 k 的元素放置在数组的前 len 个位置。
    • 最后返回处理后的数组长度 len

88. 合并两个有序数组

题目描述

88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

运行代码

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=nums1.size()-1;
m--;
n--;
while(n>=0){
    while(m>=0&&nums1[m]>nums2[n]){
        swap(nums1[i--],nums1[m--]);
    }
    swap(nums1[i--],nums2[n--]);
}
    }
};

代码思路

一、整体思路

  1. 这段代码的目的是将两个有序数组 nums1 和 nums2 合并到 nums1 中,使得合并后的 nums1 仍然保持非递减顺序。
  2. 通过从后往前遍历两个数组,比较两个数组中当前位置的元素大小,将较大的元素依次放入 nums1 的末尾,从而实现合并。

二、函数分析

  1. merge 函数:

    • 接收两个参数,分别是整数向量 nums1nums1 中有效元素的数量 m、整数向量 nums2nums2 中有效元素的数量 n
    • 首先初始化一个指针 i 指向 nums1 的最后一个位置,此时 i = nums1.size() - 1。同时将 m 和 n 分别减一,使得 m 和 n 分别指向 nums1 和 nums2 的最后一个有效元素。
  2. 循环处理:

    • 进入一个循环,条件是 n >= 0,即只要 nums2 中还有未处理的元素,就继续循环。
    • 在循环内部,首先进入一个内层循环,条件是 m >= 0 且 nums1[m] > nums2[n]。这意味着只要 nums1 中还有未处理的元素且当前 nums1 中的元素大于 nums2 中的元素,就将 nums1 中的这个较大元素与 nums1 的末尾元素交换,并将 m 和 i 分别减一。
    • 当内层循环结束后,说明 nums1 中当前位置的元素小于等于 nums2 中的元素,或者 nums1 已经处理完了。此时将 nums2 中的当前元素与 nums1 的末尾元素交换,并将 n 和 i 分别减一。

4. 寻找两个正序数组的中位数

题目描述

4. 寻找两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

运行代码

class Solution {
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
		int n = nums1.size();
		int m = nums2.size();
		if (n > m)  //保证数组1一定最短
		{
			return findMedianSortedArrays(nums2, nums1);
		}
		// Ci 为第i个数组的割,比如C1为2时表示第1个数组只有2个元素。LMaxi为第i个数组割后的左元素。RMini为第i个数组割后的右元素。
		int LMax1, LMax2, RMin1, RMin2, c1, c2, lo = 0, hi = 2 * n;  //我们目前是虚拟加了'#'所以数组1是2*n长度
		while (lo <= hi)   //二分
		{
			c1 = (lo + hi) / 2;  //c1是二分的结果
			c2 = m + n - c1;

			LMax1 = (c1 == 0) ? INT_MIN : nums1[(c1 - 1) / 2];
			RMin1 = (c1 == 2 * n) ? INT_MAX : nums1[c1 / 2];
			LMax2 = (c2 == 0) ? INT_MIN : nums2[(c2 - 1) / 2];
			RMin2 = (c2 == 2 * m) ? INT_MAX : nums2[c2 / 2];

			if (LMax1 > RMin2)
				hi = c1 - 1;
			else if (LMax2 > RMin1)
				lo = c1 + 1;
			else
				break;
		}
		return (max(LMax1, LMax2) + min(RMin1, RMin2)) / 2.0;
	}
};

代码思路

一、整体思路

该算法的目的是找到两个正序数组的中位数。整体采用了二分查找的思想,通过不断调整两个数组的划分位置,使得划分后的左右两部分满足特定条件,从而确定中位数的位置。

二、关键变量解释

  • nm:分别表示数组nums1nums2的大小。
  • LMax1LMax2RMin1RMin2:分别表示在当前划分下,数组nums1nums2划分后的左部分最大值和右部分最小值。
  • c1c2:分别表示对数组nums1nums2进行划分的位置。实际上是一个虚拟的划分点,将数组分为左右两部分。
  • lohi:二分查找的上下界,初始时lo = 0hi = 2 * n,表示对数组nums1的划分位置的搜索范围。

三、函数分析

  1. 首先计算两个输入数组的大小nm,如果n > m,则交换两个数组,保证nums1是较短的数组,这样可以减少时间复杂度。
  2. 接着定义了一系列变量,包括用于二分查找的上下界lohi,以及用于存储划分后左右部分最大值和最小值的变量。
  3. 进入while循环进行二分查找,循环条件是lo <= hi
  4. 在每次循环中,计算当前的划分位置c1c2。根据c1c2计算出两个数组划分后的左部分最大值和右部分最小值。
  5. 如果LMax1 > RMin2,说明当前划分位置不合适,需要将hi更新为c1 - 1,缩小搜索范围;如果LMax2 > RMin1,说明当前划分位置也不合适,需要将lo更新为c1 + 1,扩大搜索范围;如果满足条件,则跳出循环。
  6. 最后,根据找到的划分位置,计算中位数并返回。如果两个数组的总长度是偶数,则中位数是左右两部分最大值的最大值与左右两部分最小值的最小值的平均值;如果总长度是奇数,则中位数是左部分最大值和右部分最小值中的较小值。

标签:数组,nums,元素,len,有序,nums1,nums2,线性表
From: https://blog.csdn.net/u014114223/article/details/142371018

相关文章

  • 数据结构之线性表——LeetCode:82. 删除排序链表中的重复元素 II,21. 合并两个有序链
    82.删除排序链表中的重复元素II题目描述82.删除排序链表中的重复元素II给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。运行代码classSolution{public:ListNode*deleteDuplicates(ListNode......
  • 小美的数组合并(美团20240427年暑期实习笔试真题)
    题目:小美的数组合并小美拿到了一个数组,她每次操作可以将两个相邻元素ai合并为一个元素,合并后的元素为原来两个元素之和。小美希望最终数组的最小值不小于k。她想知道有多少种不同的合并结果?输入描述第一行输入两个正整数n,k,代表数组大小和数组的最大值。第二行输入个正整数ai,......
  • c语言 一/二维数组
    菜鸟学习笔记 欢迎大佬指教一维数组:  声明:int arr[10];//声明一个一位数组可以存放10个(int)整形的数组计算该数组的大小:sizeof(arr) 会返回数组 a 占用的总字节数。sizeof(int) 会返回单个 int 类型变量占用的字节数。   我们使用总字节数/单个字节数......
  • 稀疏数组
    publicclassArraysDemo02{publicstaticvoidmain(String[]args){int[][]a=newint[11][11];a[1][2]=1;a[2][3]=2;for(int[]ints:a){for(inti:ints){System.out.print(i+"\t");}System.out.println();}System.out.println(&q......
  • 树状数组浅谈
    什么是树状数组树状数组是一种码量小,常数小,支持单点修改和区间查询的数据结构。树状数组维护的信息和运算需要满足结合律并且可差分注意gcd和max操作虽然满足结合律,但不可差分,因此不能使用树状数组维护其实,树状数组能做的,线段树都能做,线段树能做的,树状数组不一定能做,但线段树......
  • C++速通LeetCode中等第10题-轮转数组(四种方法)
    方法一:巧用deque双向队列容器classSolution{public:voidrotate(vector<int>&nums,intk){deque<int>q;inttmp;if(nums.size()>1){for(autonum:nums)q.push_back(num);......
  • C++:数组与字符串
    一、数组         数组是一种存储若干元素的数据类型,在诸多编程语言中存在,其显著的特点是元素通常是在物理层面上连续存储的(逻辑上的数组,比如链表,可能不是),并且具有极快的元素访问速度。    数组通常是同构的(homogenous ),即数组中的元素都是同一类型的,......
  • Leetcode 2464. 有效分割中的最少子数组数目
    1.题目基本信息1.1.题目描述给定一个整数数组nums。如果要将整数数组nums拆分为子数组后是有效的,则必须满足:每个子数组的第一个和最后一个元素的最大公约数大于1,且nums的每个元素只属于一个子数组。返回nums的有效子数组拆分中的最少子数组数目。如果不能进......
  • 返回数组中的最大元素个数
    /***返回数组中的最大元素个数*约束:*数组大小1<=size<=10to5*数组元素大小1<=arrList[i]<=10to7*@paramcandles*@return*/publicstaticintbirthdayCakeCandles(List<Integer>candles){if(cand......
  • 【信号传输】DMA传输只能收到一半数据,发送123456 只能收到 123, 发送abcd只能收到ab,缓
    系列文章目录1.元件基础2.电路设计3.PCB设计4.元件焊接5.板子调试6.程序设计7.算法学习8.编写exe9.检测标准10.项目举例11.职业规划文章目录方案一、改DMA中断方案二、改数据类型方案三、改数据长度后记方案一、改DMA中断每个DMA通道都可以在DMA传......