leetcode数组刷题(一)——数组一些加加减减
准备找饭饭啦,开始刷题啦,菜菜的自己记录一些东西,以备自己不灵光的脑子
26、删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int length = nums.size();
for(int i = 0;i<length-1;i++){
if(nums[i]==nums[i+1]){
for(int j = i+1;j<length-1;j++){
nums[j]=nums[j+1];
}
length--;
i--;
}
}
return length;
}
};
问题:第一次没写i–,无法判断连续大于等于3个相同数字的重复项,所以如果有相同数字,要从移位后的当前位置进行判断,但是问题是该代码说运行时间超时……所以借鉴官方解答如下
\\如果数组 \textit{nums}nums 的长度为0,则数组不包含任何元素,因此返回0。
\\定义两个指针分别为快指针和慢指针,快指针表示遍历数组到达的下标位置,慢指针表示下一个不同元素要填入的下标位置,初始时两个指针都指向下标1。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int n = nums.size();
if (n == 0) {
return 0;
}
int fast = 1, slow = 1;
while (fast < n) {
if (nums[fast] != nums[fast - 1]) {
nums[slow] = nums[fast];
++slow;
}
++fast;
}
return slow;
}
};
27、 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
for(int i=0;i<n;i++){
if(nums[i]==val){
for(int j=i;j<n-1;j++){
nums[j]=nums[j+1];
}
n--;
i--;
}
}
return n;
}
};
与上一题思路相同,应该也可以用双指针进行计算,官方有说明。
35.、搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
for(int i=0;i<n;i++){
if(nums[i]>=target){
return i;
}
if((nums[i]<target)&&(i==n-1)){
return i+1;
}
}
return 0;
}
};
hhh看了眼评论被批斗了一点都没有算法概念,官方思路二分法查找
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int left = 0, right = n - 1, ans = n;
while (left <= right) {
int mid = ((right - left)/2) + left;
if (target <= nums[mid]) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
};
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 = 0;int j = 0;
int results[m+n];
int pop = 0;
for(int k=0;k<m+n;k++){
if(i==m) pop = nums2[j++];
else if(j==n) pop = nums1[i++];
else if(nums1[i]>=nums2[j]) pop = nums2[j++];
else pop = nums1[i++];
results[k] = pop;
}
for(int k=0;k<m+n;k++) nums1[k] = results[k];
}
};
有个小发现,此处数组的定义与之前不同,分析后应该是此处的数字元素个数是常数,之前是个变量,所以没法用来定义,所以标准的定义方式即可。
另一个想法,没有说要在原数组操作的不需要担心内存问题,比较移位操作的计算量更大。
当然最简单的是直接排序,顺便熟悉了一下排序自带函数应该怎么写:升序:sort(s.begin(),s.end(),less<data_type>())
降序:sort(s.begin(),s.end(),greater<data_type>())
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for(int i=0;i<n;i++)nums1[i+m] = nums2[i];
sort(nums1.begin(),nums1.end());
}
};
108、将有序数组转换为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return helper(nums, 0, nums.size() - 1);
}
TreeNode* helper(vector<int>& nums, int left, int right) {
if (left > right) {
return nullptr;
}
// 总是选择中间位置左边的数字作为根节点
int mid = (left + right) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = helper(nums, left, mid - 1);
root->right = helper(nums, mid + 1, right);
return root;
}
};
emmmm,小白没有学习过二叉树,所以直接看的官方解答,学习学习。