算法详解:杨辉三角 | 合并俩个有序数组 | 删除有序数组中的重复项

2023-12-07 11:52

本文主要是介绍算法详解:杨辉三角 | 合并俩个有序数组 | 删除有序数组中的重复项,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


前言:本次分享题目全部来自力扣网,大家可以自行选择挑战,详细链接:

118. 杨辉三角 - 力扣(LeetCode)

88. 合并两个有序数组 - 力扣(LeetCode)

26. 删除有序数组中的重复项 - 力扣(LeetCode)

目录

一.杨辉三角

思路:

完整代码:

二.合并俩个有序数组

思路:

完整代码:

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

思路:

完整代码:


一.杨辉三角

题目:给定一个非负整数 numRows生成「杨辉三角」的前 numRows 行(1 <= numRows <= 30)

注意:在「杨辉三角」中,每个数是它左上方和右上方的数的和

示例一:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

 示例二:

输入: numRows = 1
输出: [[1]]

思路:

我们可以将杨辉三角图形进行转个方向,改为一个阶梯型的可能更适合我们理解,对于这样的阶梯型的数据,我们很自然就会联想到二维数组,那杨辉三角可不可以用二维数组实现呢?

对于每一行数据,第一个和最后一个都是1,剩下的数据都是上一行的同一位置的数据加上前一个数据,也就是说我们在实现每一行的数据的时候都需要用到上一行的数据。为了更高效的完成上述的过程我们可以使用二维的顺序表代替二维数组进行操作。

在确定了使用二维顺序表后,我们需要定义一个总的顺序表去存放每一行对应的顺序表,用外层for循环确定到底有多少行,用内层for循环确定每一行的元素,以上就确定了本题的大概框架。

对于几个细节需要注意:

总结观察杨辉三角,所有1的位置都是在每一行的开头和结尾,开头很简单内层for循环 j=0 ;的时候就是开头位置,而每一行的最后一个元素,我们仔细观察他的坐标就会发现,他的行数和列数相等,也就是外层for循环的循环变量 i 与内层for循环变量 j 相等的时候,总结来说当循环变量 (j == 0 || j == i) 的时候我们就对行顺序表添加元素 “1” 

对于非1的数据,我们需要访问上一行的数据,通过 .get( i-1) 可以拿到上一行的顺序表,拿到上一行的顺序表后再分别拿到这一行的 j 位置和 j-1 位置的元素,然后相加,相加后的结果就是我们要的值,最后再将这个值使用 .add 添加到这一行的顺序表中就可以

完整代码:

class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<>();for (int i = 0; i < numRows; i++) {//新定义一行List<Integer> row = new ArrayList<>();for (int j = 0; j <= i; j++) {if (j == 0 || j == i) {row.add(1);}else {//添加上一行的数据(上一行的j-1和j位置)row.add(ret.get(i-1).get(j-1) + ret.get(i-1).get(j));}}//每一次将新的一行加入总的二维顺序表中ret.add(row);}return ret;}
}

二.合并俩个有序数组

题目:给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

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

示例一:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] 

示例二:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 

 示例三:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1]

思路:

对于一个数组,我们要将其合并到一个全新的数组中,我们可以使用俩个指针,分别指向俩个数组,然后对比俩个指针谁的值小,小的值就放入新数组中,并且指针后移

对于放入数据一共有4种情况,我们分别对应处理一下:

  1. nums1 的数据小于 nums2 的数据:将 nums1 的数据放入新数组,并且指针pA后移
  2. nums1 的数据大于 nums2 的数据:将 nums2 的数据放入新数组,并且指针pB后移
  3. nums1 的数据已经排除完了,但是 nums2 还有元素:将 nums2 的元素放入新数组,并且指针pB后移
  4.  nums2 的数据已经排除完了,但是 nums1 还有元素:将nums1的元素放入新数组,并且指针pA后移

我们使用一个while循环来包含所有的情况遍历,然后每一次判断都将一个数据通过临时变量放入新数组中,为了和服题目要求,将最后的结果再覆盖到数组1中

完整代码:

class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int pA = 0;int pB = 0;int cur = 0;int[] sordNum = new int[m + n];while (pA < m || pB < n) {if (pA == m) {//nums1已满,放入nums2cur = nums2[pB++];} else if (pB == n) {//nums2已满,放入nums1cur = nums1[pA++];} else if (nums1[pA] < nums2[pB]) {//nums1的数据小于nums2cur = nums1[pA++];} else {//nums1的数据大于等于nums2cur = nums2[pB++];}sordNum[pA + pB - 1] = cur;}for (int j = 0; j != m + n; ++j) {nums1[j] = sordNum[j];}}
}

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

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

示例一:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]

示例二:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]

思路:

对于这里的删除,我们可以巧妙的利用,具体来说我们可以将不重复的元素放在数组前面,然后我们只返回这部分不重复的元素,这样就变相的达到了删除的目标

完整代码:

class Solution {public int removeDuplicates(int[] nums) {//快慢指针int left = 0;int right = 1;while(right < nums.length){if(nums[left] != nums[right]){left++;nums[left] = nums[right];}right++;}return left + 1;}
}



  本次的分享就到此为止了,希望我的分享能给您带来帮助,也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见

这篇关于算法详解:杨辉三角 | 合并俩个有序数组 | 删除有序数组中的重复项的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/465771

相关文章

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

python中的flask_sqlalchemy的使用及示例详解

《python中的flask_sqlalchemy的使用及示例详解》文章主要介绍了在使用SQLAlchemy创建模型实例时,通过元类动态创建实例的方式,并说明了如何在实例化时执行__init__方法,... 目录@orm.reconstructorSQLAlchemy的回滚关联其他模型数据库基本操作将数据添

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param