Search in Rotated Sorted Array 旋转数组里查找数 @LeetCode

二分法的变型题

FollowUp 是如果数组里有重复元素怎么办?

其实没所谓。

http://blog.csdn.net/fightforyourdream/article/details/16857291


package Level4;

/**
 * Search in Rotated Sorted Array
 * 
 * Suppose a sorted array is rotated at some pivot unknown to you beforehand.
 * 
 * (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
 * 
 * You are given a target value to search. If found in the array return its
 * index, otherwise return -1.
 * 
 * You may assume no duplicate exists in the array.
 * 
 */
public class S33 {

	public static void main(String[] args) {
		int[] A = {2, 3, 4, 5, 6, 0, 1};
		System.out.println(search(A, 0));
	}

	public static int search(int[] A, int target) {
		return rec(A, target, 0, A.length-1);
	}
	
	// 递归查找
	public static int rec(int[] A, int target, int low, int high){
		if(low > high){				// 没找到的情况
			return -1;
		}
		
		int mid = low + (high-low)/2;
		if(A[mid] == target){		// 找到了
			return mid;
		}
		
		int res = rec(A, target, low, mid-1);		// 在左侧查找
		if(res == -1){			// 如果左侧没找到,继续在右侧查找
			res = rec(A, target, mid+1, high);
		}
		
		return res;
	}

}



解法就是直接分别对左半侧和右半侧搜索,用递归实现

public class Solution {
    public int search(int[] A, int target) {
        return rec(A, target, 0, A.length-1);
    }
    
    public int rec(int[] A, int target, int low, int high){
        if(low > high){
            return -1;
        }
        
        int mid = low + (high-low)/2;
        if(A[mid] == target){
            return mid;
        }
        int pos = rec(A, target, mid+1, high);
        if(pos != -1){
            return pos;
        }else{
            return rec(A, target, low, mid-1);
        }
    }
}


I have updated the problem description to assume that there exists no duplicate in the array. Some readers have noted that the below code does not work for input with duplicates. For example, for input “1 2 1 1 1 1″, the binary search method below would not work, as there is no way to know if an element exists in the array without going through each element one by one.

At first look, we know that we can do a linear search in O(n) time. But linear search does not need the elements to be sorted in any way.

First, we know that it is a sorted array that’s been rotated. Although we do not know where the rotation pivot is, there is a property we can take advantage of. Here, we make an observation that a rotated array can be classified as two sub-array that is sorted (i.e., 4 5 6 7 0 1 2 consists of two sub-arrays 4 5 6 7 and 0 1 2.

Do not jump to conclusion that we need to first find the location of the pivot and then do binary search on both sub-arrays. Although this can be done in O(lg n) time, this is not necessary and is more complicated.

In fact, we don’t need to know where the pivot is. Look at the middle element (7). Compare it with the left most (4) and right most element (2). The left most element (4) is less than (7). This gives us valuable information — All elements in the bottom half must be in strictly increasing order. Therefore, if the key we are looking for is between 4 and 7, we eliminate the upper half; if not, we eliminate the bottom half.

When left index is greater than right index, we have to stop searching as the key we are finding is not in the array.

Since we reduce the search space by half each time, the complexity must be in the order of O(lg n). It is similar to binary search but is somehow modified for this problem. In fact, this is more general than binary search, as it works for both rotated and non-rotated arrays.

二分法的·精髓在于只要能做到每次扔掉一半

int rotated_binary_search(int A[], int N, int key) {
  int L = 0;
  int R = N - 1;
 
  while (L <= R) {
    // Avoid overflow, same as M=(L+R)/2
    int M = L + ((R - L) / 2);
    if (A[M] == key) return M;
 
    // the bottom half is sorted
    if (A[L] <= A[M]) {
      if (A[L] <= key && key < A[M])
        R = M - 1;
      else
        L = M + 1;
    }
    // the upper half is sorted
    else {
      if (A[M] < key && key <= A[R])
        L = M + 1;
      else 
        R = M - 1;
    }
  }
  return -1;
}


扩展:

如何找pivot点:相当于找到最小的那个点:把中点和右边的点比较

int FindSortedArrayRotation(int A[], int N) {
  int L = 0;
  int R = N - 1;
  
  while (A[L] > A[R]) {
    int M = L + (R - L) / 2;
    if (A[M] > A[R])
      L = M + 1;
    else
      R = M;
  }
  return L;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、据库操作、用户权限管理等关键技术。 据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的据库设计文件。这些文件通常包括据库结构图、据表设计文档,以及示例据SQL脚本。用户可以通过这些文件快速搭建项目所需的据库环境,并了解各个据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
是的,你可以使用`minAreaRect`函返回的旋转角度来旋转图像。`minAreaRect`函可以用于计算包围点集的最小旋转矩形,其中包括旋转角度信息。 以下是一个示例代码,展示了如何使用`minAreaRect`函返回的旋转角度来旋转图像: ```cpp #include <opencv2/opencv.hpp> int main() { // 读取图像 cv::Mat image = cv::imread("image.jpg"); // 定义点集 std::vector<cv::Point2f> points; // 添加点到点集中,这只是示例,你需要根据实际情况添加点 points.push_back(cv::Point2f(100, 100)); points.push_back(cv::Point2f(200, 100)); points.push_back(cv::Point2f(200, 200)); points.push_back(cv::Point2f(100, 200)); // 计算最小旋转矩形 cv::RotatedRect rotatedRect = cv::minAreaRect(points); // 获取旋转角度 float angle = rotatedRect.angle; // 创建旋转矩阵 cv::Mat rotationMatrix = cv::getRotationMatrix2D(rotatedRect.center, angle, 1.0); // 应用旋转矩阵进行旋转 cv::Mat rotatedImage; cv::warpAffine(image, rotatedImage, rotationMatrix, image.size()); // 显示结果 cv::imshow("Original Image", image); cv::imshow("Rotated Image", rotatedImage); cv::waitKey(0); cv::destroyAllWindows(); return 0; } ``` 在上述代码中,我们首先使用`imread`函读取图像。然后,我们定义一个点集`points`,并添加一些点到点集中(这只是示例,你需要根据实际情况添加点)。 接下来,我们使用`minAreaRect`函计算点集的最小旋转矩形,其中包括旋转角度信息。我们通过访问`RotatedRect`结构体的`angle`成员变量,获取旋转角度。 然后,我们使用`getRotationMatrix2D`函创建一个旋转矩阵,该矩阵将围绕旋转中心和旋转角度进行旋转。 最后,我们使用`warpAffine`函应用旋转矩阵,对原始图像进行旋转操作。这样,我们可以得到一个名为`rotatedImage`的图像,它是原始图像经过旋转后的结果。 最后,我们使用`imshow`函显示原始图像和旋转后的图像,并使用`waitKey`和`destroyAllWindows`函等待用户按下键盘并关闭窗口。 请注意,这的点集是示例用途,你需要根据实际情况提供合适的点集来计算最小旋转矩形。同时,你也可以根据需要对旋转角度进行调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值