本专栏使用C/C++语言编写数据结构
C语言专栏:C语言基本语法、基本操作、相关库函数的编写,相关内存分析
C++专栏:C++基本语法、C++相关结构剖析,详细例题,相关小型Demo的编写
数据结构专栏:基本数据结构原理介绍,代码实现,相关Leetcode例题讲解剖析
干货满满,陆续更新ing
本文为与线性表相关的Leetcode题目
线性表
1. 存在重复元素
给你一个整数数组 nums。如果任一值在数组中出现至少两次,返回 true;如果数组中每个元素互不相同,返回false 。
示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:
输入:nums = [1,2,3,4]
输出:false
示例 3:
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
排序
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
//对vector内数值进行排序
sort(nums.begin(),nums.end());
for(int i = 0;i<nums.size()-1;i++){
if(nums[i]==nums[i+1]){
return true;
}
}
return false;
}
};
时间复杂度:O(NlogN),其中N为数组的长度。需要对数组进行排序。
空间复杂度:O(logN),其中N为数组的长度。注意我们在这里应当考虑递归调用栈的深度。
2. 消失的数字
数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。在O(n)时间内完成
示例 1:
输入:[3,0,1]
输出:2
示例 2:
输入:[9,6,4,2,3,5,7,0,1]
输出:8
哈希表
class Solution {
public:
int missingNumber(vector<int>& nums) {
vector<int>num;
num.assign(nums.size()+1,-1);
for(int i = 0;i<nums.size();i++){
num[nums[i]]=nums[i];
}
int i = 0;
for(i = 0;i<num.size();i++){
if(num[i]==-1){
break;
}
}
return i;
}
};
如上图所示,初始化一个值全为-1的num数组,将nums中的值放到值对应下标的num中,最后遍历num,值为-1所对应的下标即为缺失的整数。
3. 删除有序数组中的重复项
给你一个升序排列的数组nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致 。
如果在删除重复项之后有k个元素,那么nums的前k个元素应该保存最终结果。
将最终结果插入nums的前k个位置后返回k。
在使用 O(1) 额外空间的条件下完成。
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度2,并且原数组 nums 的前两个元素被修改为1, 2。不需要考虑数组中超出新长度后面的元素。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int src = 0;
int dst = 0;
while(dst < nums.size()){
if(nums[dst]!=nums[src]){
src++;
nums[src]=nums[dst];
}else{
dst++;
}
}
return src+1;
}
};
时间复杂度:O(N),其中N是数组的长度。
空间复杂度:O(1),只需要使用常数的额外空间。
4. 合并两个有序数组
给你两个按非递减顺序排列的整数数组 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]
归并思想
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m-1, j = n-1;
int dst = m+n-1;
while(i >= 0 && j >= 0){
if(nums1[i] > nums2[j]){
nums1[dst--] = nums1[i--];
}else{
nums1[dst--] = nums2[j--];
}
}
while(j >= 0){
nums1[dst--] = nums2[j--];
}
}
};
第一种情况:
(1)i与j分别为nums1与nums2的最后一个有效元素的下标,dst为nums1数组最后一个元素的下标,比较nums1[i]与nums2[j]的大小,将较大的值赋值给nums1[dst],同时,移动指针。
因为数组中的元素为递增存放,故每次比较将较大的元素赋值给nums1[dst]。
(2)移动dst与j,进行赋值
(3)nums1[i] > nums2[j],故将较大值nums1[i]赋值给nums1[dst]。
(4)nums1[i]==nums2[j];根据代码,将进入else分支,将nums1[j]赋值给nums1[dst]。
第二种情况:
(1)第二种情况中,nums1中所有元素均大于nums2中的元素,进行比较,将较大值存放于dst指向的数组中。
(2)依次进行比较,赋值,挪动双指针。
(3)由下图可知,当nums1中的元素全部都比较结束后,需要将nums2中的元素全部都赋值到nums1中。
(4)如下图所示,赋值完成,合并数组完成。
看到这里,如果感觉文章对你有帮助,不要忘记一键三连哦!