【Leetcode】移除元素、轮转数组

发布于:2022-10-29 ⋅ 阅读:(440) ⋅ 点赞:(0)

作者:一个喜欢猫咪的的程序员

专栏:《Leetcode》

喜欢的话:世间因为少年的挺身而出,而更加瑰丽。                                  ——《人民日报》

目录

27. 移除元素

 189.轮转数组:



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.轮转数组:

189. 轮转数组https://leetcode.cn/problems/rotate-array/ 题目:

给你一个数组,将数组中的元素向右轮转 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);
}


网站公告

今日签到

点亮在社区的每一天
去签到