leetcode33/ 81——搜索旋转排序数组

本文介绍了三种与数组操作和查找算法相关的编程问题:1) 字符串循环左移,通过取余实现;2) 二分查找算法,用于有序数组中查找特定值;3) 搜索旋转排序数组,考虑了数组旋转后的位置。针对每种问题,提供了详细思路和Java代码实现,包括使用内置方法和翻转数组的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

零、查找算法

https://blog.51cto.com/u_15047490/2561082

二分查找参考:https://www.cnblogs.com/gzshan/p/12570332.html

一、旋转数组

对应牛客43题

1.题目

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列 S ,请你把其循环左移 K 位后的序列输出(保证 K 小于等于 S 的长度)。例如,字符序列 S = ”abcXYZdef” , 要求输出循环左移 3 位后的结果,即 “XYZdefabc” 。是不是很简单?OK,搞定它!

数据范围:输入的字符串长度满足 ,
进阶:空间复杂度 ,时间复杂度

2.思路

注意点,要注意n大于str长度的情况,可通过取余实现
如:
输入:“aab”,10
返回值:“aba”

3.代码

//内置方法
public class Solution{
	private chars reverse(char str, int n){
		if (str == null || str.length()<= 1 || n <= 0 ) return str;
		if ( n > str.length()) n= n%str.length();
		return str.subString(n) + str.subString(0,n);
}
}
//翻转三次
public class Solution {
    public String LeftRotateString(String str,int n) {
        // base case
        if (str == null || str.length()<= 1 || n<=0) return str;
        if (n> str.length()) n= n%str.length();
        //新建数组
        char [] chars = str.toCharArray();
        //左右翻转,然后整体翻转
        reverse (chars, 0, n-1);
        reverse (chars, n , str.length()-1);
        reverse (chars, 0, str.length()-1);
        return new String(chars);
    }
    private void reverse (char[] chars, int start, int end ){
        while(start < end){
            char temp = chars [start];
            chars[start] = chars[end];
            chars[end] = temp;
            start ++;
            end--;
        }
    }
}

二、二分查找

1.题目

在有序数组中查找一个特定的值target

2.思路

二分查找

  • 若 target == nums[mid],直接返回
  • 若 target < nums[mid],则 target 位于左侧区间 [left,mid) 中。令 right = mid-1,在左侧区间查找
  • 若 target > nums[mid],则 target 位于右侧区间 (mid,right] 中。令 left = mid+1,在右侧区间查找

3.代码

public class Solution{
	   public boolean search(int[] nums, int target) {
       		if(nums==null || nums.length==0) return false;
      		int low=0,high=nums.length-1;
        	while(low<=high){
         		 int mid=low+(high-low)/2;
           		 if(nums[mid]==target)  return true;
                else if(target<nums[mid]){ 
                high=mid-1;
                }else{
                low=mid+1;
            }
        }
        return false;
    }
}

三、搜索旋转排序数组

1.题目

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

示例

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

2.思路

二分查找,从任一位置进行分隔,则必有其中一半是有序的。因此,我们可以仍然从中点位置进行分隔,然后通过将最左边元素nums[low]和nums[mid]进行比较,从而可以判断出来,是左侧还是右侧是连续有序的,进而可以选择接下来继续选择哪一边进行继续查找。
1、若 target == nums[mid],直接返回
2、若 nums[left] <= nums[mid],说明左侧区间 [left,mid]「连续递增」。此时:
  若 nums[left] <= target <= nums[mid],说明 target 位于左侧。令 right = mid-1,在左侧区间查找
  否则,令 left = mid+1,在右侧区间查找
3、否则,说明右侧区间 [mid,right]「连续递增」。
  此时:
若 nums[mid] <= target <= nums[right],说明 target 位于右侧区间。令 left = mid+1,在右侧区间查找
  否则,令 right = mid-1,在左侧区间查找

3.代码

public class Solution {
    public int search(int[] nums, int target) {
        if(nums==null || nums.length==0)
            return -1;
        int low=0,high=nums.length-1;
        while(low<=high){
            int mid=low+(high-low)/2;
            if(nums[mid]==target)
                return mid;
            else if(nums[low]<=nums[mid]){  //左侧连续
                if(target<nums[mid] && target>=nums[low])
                    high=mid-1;
                else
                    low=mid+1;
            }else{      //右侧连续
                if(target>nums[mid] && target<=nums[high])
                    low=mid+1;
                else
                    high=mid-1;
            }
        }
        return -1;
    
}

四、搜索旋转排序数组II

1.题目

已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。

给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。

2.思路

本题是上一题的延续,其区别在于数组中是否包含重复元素,当数组中允许元素重复时,如果nums[low]和nums[mid]是相等的,那我们就无法判断究竟是哪一边连续有序,这时我们可以让指针只移动一位,相当于排除一个元素。其余和上题基本相同。

3.代码

class Solution {
    public boolean search(int[] nums, int target) {
        //base case
        if (nums == null || nums.length == 0 ) return false;
        //二分查找
        int left = 0;
        int right = nums.length-1;
        while ( left <= right){
            int mid = left +(right - left)/2;
            if (nums[mid] == target)  return true;
            if (nums[left] == nums[mid]) left ++;
            else if (nums[left] < nums[mid]){
                if (nums[left]<= target && target <nums[mid]) right = mid-1;
                else{
                    left = mid+1;
                }
            }else{
                if(target > nums[mid] && target <= nums[right]) left = mid+1;
                else {
                    right = mid -1;
                }
            }
            }
        return false;    
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值