作者:一个喜欢猫咪的的程序员
专栏:《Leetcode》
喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》
目录
27. 移除元素
27. 移除元素
https://leetcode.cn/problems/remove-element/
题目:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例:
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
思路一:
我们以示例2为例子:
0,1,2,2,3,0,4,2 我们不是要返回整数嘛,我们可以先算出来等于val的个数,利用numsSize--来算出返回的整数。我们从0(i)开始往后遍历,找到等于val的值,如果有就从numsSize-1的位置(f)向前遍历找一个不等val的值将其赋给val这个值的下标(比如:将示例2中的4赋给第一个2。)然后f-1一下找到上一个位置(这里不是j-1是因为要保证后面n个数都要被找过,直接用j-1的话会少一个或者两个...)。当我们把f遍历到i的下一个位置时,从后面遍历上来这个循环就不会循环了,我们需要额外写这种情况。
时间复杂度:O(N^2) 空间复杂度:O(1)
思路二:双指针
利用左指针left找到等于val的值,如果将右指针right位置的值赋过去,然后右指针左移一位right--
如果赋值过来的值也是val,将右指针的下一个值也赋值过来就好了,直到左指针的值不为val。
当左指针left 和右指针 right重合的时候,左右指针遍历完数组中所有的元素。
时间复杂度:O(N) 空间复杂度:O(1)
代码实现:
思路一:
int removeElement(int* nums, int numsSize, int val){ int n=numsSize; for(int i=0;i<numsSize;i++) { if(*(nums+i)==val) n--; } int f=numsSize-1; for(int i=0;i<numsSize;i++) { if(*(nums+i)==val) { if(i+1==f) { *(nums+i)=*(nums+i+1); continue; } else { for(int j=f;j>i;j--) { if(*(nums+j)!=val) { *(nums+i)=*(nums+j); f=j-1; break; } } } } } numsSize=n; return numsSize; }
思路二:
int removeElement(int* nums, int numsSize, int val){ int left=0; int right=numsSize; while(left<right) { if(*(nums+left)==val) { *(nums+left)=*(nums+right-1); right--; } else left++; } return left; }
189.轮转数组:
题目:
给你一个数组,将数组中的元素向右轮转
k
个位置,其中k
是非负数。
示例:
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
思路:
思路一:利用额外的数组
将后k个元素先存在额外数组n[numsSize]中,剩下的numssize-k个元素在存进去这个额外数组中,然后再将这个额外数组赋给nums。
时间复杂度:O(N) 空间复杂度:O(N)
思路二:数组翻转
将前numsSize-k个先倒序,再将后k个倒序,然后再整体倒序。
时间复杂度:O(N) 空间复杂度:O(1)
代码实现:
思路一:
void rotate(int* nums, int numsSize, int k){ int n[numsSize]; k=k%numsSize; for(int i=0;i<k;i++) { n[i]=*(nums+numsSize-k+i); } for(int i=0;i<numsSize-k;i++) { n[k+i]=*(nums+i); } for(int i=0;i<numsSize;i++) { *(nums+i)=n[i]; } }
思路二:
void reverse(int* n,int begin,int end) { while(begin<end) { int tmp=*(n+begin); *(n+begin)=*(n+end); *(n+end)=tmp; end--; begin++; } } void rotate(int* nums, int numsSize, int k){ k=k%numsSize; reverse(nums,0,numsSize-k-1); reverse(nums,numsSize-k,numsSize-1); reverse(nums,0,numsSize-1); }