旋转数组专题

1.力扣189

时间复杂度,空间复杂度都是O(N)的暴力法:

class Solution 
{
    public void rotate(int[] nums, int k) 
    {
      //[1,2]  k=3,当k>nums.length的时候,k要取一个模
      k=k%nums.length;
     
      //就是将k个后面的数移到最前面去
      //比如k=3,就是将最后三个数移到最前面去
      int[] result=new int[nums.length];

      //将原数组nums后面k个数放到result数组里面
      int j=0;
      for(int i=nums.length-k;i<nums.length;i++)
      {
          result[j]=nums[i];
          j++;
      }
      //将原数组nums前面nums.length-k个元素也放到result数组里面
      for(int i=0;i<nums.length-k;i++)
      {
          result[j]=nums[i];
          j++;
      }
      for(int m=0;m<nums.length;m++)
      {
          nums[m]=result[m];
      }
    }
}

方法二:三次反转

时间复杂度是O(N),空间复杂度是O(1)

class Solution 
{
    public void rotate(int[] nums, int k) 
    {
     k=k%nums.length;
     //反转后k个数
      reverse(nums,nums.length-k,nums.length-1);
      //反转前n-k个数
      reverse(nums,0,nums.length-k-1);
      //整体再进行一次反转
      reverse(nums,0,nums.length-1);
    }
    public void reverse(int[] nums,int left,int right)
    {
        int length=right-left+1;
        while(left<right)
        {
            int temp=nums[right];
            nums[right]=nums[left];
            nums[left]=temp;
            left++;
            right--;
        }
    }
}

2.力扣33  搜索旋转排序数组

旋转数组其实是本来是一个升序数组,前面小后面大

然后把后面大的拿到前面来,所以最后的局面就是:前面大后面小,区域1最小的数也比区域2最大的数大

 

 第一步是先判断是前半段长还是后半段长的情形

第二步:target处在nums[left]~nums[mid]区间还是nums[mid]~nums[right]区间

如果target处在nums[left]~nums[mid],那就right=mid-1

如果target处在nums[mid]~nums[right],那就left=mid+1

第三步:left=mid+1或者是right=mid-1

class Solution
{
    public int search(int[] nums, int target)
    {
        int left=0;
        int right=nums.length-1;
        int mid=0;

        while(left<=right)
        {
          mid=(left+right)/2;

          if(nums[mid]==target)   return  mid;
          if(nums[left]==target)  return   left;
          if(nums[right]==target)  return   right;

          //后比前大,说明[left,mid]在区域1,说明前半段更长
          //target可能处在两个区域nums[left]~nums[mid],或者是nums[mid]~nums[right]
          if(nums[left]<nums[mid])
          {
              //当处在nums[left]~nums[mid]
              if(nums[left]<target&&target<nums[mid])
              {
                  right=mid-1;
              }
              else//如果target处在nums[mid]~nums[right]
              {
                  left=mid+1;
              }
          }

          //前比后大,nums[left]>=nums[mid],说明mid在区域2,后半段更长
          //target可能处在两个区域nums[left]~nums[mid],或者是nums[mid]~nums[right]
          else
          {
             if(nums[mid]<target&&target<nums[right])
             {
                 left=mid+1;
             }
             else
             {
                 right=mid-1;
             }
          }
        }
        return  -1;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值