33. Search in Rotated Sorted Array
题目:在一个被旋转一次的递增数组中找到目标值。
思路:二分法——思路一定要清晰!!!当mid和目标值不等时,判断mid和start的大小,大于说明旋转位置在后面,反之在前面。在后面的时候start-mid是递增的,可以直接判断目标值在不在其中。同理,在前面的时候mid-end是递增的,可以直接判断目标值在不在其中。
public class Solution {
public int search(int[] nums, int target) {
int ret = 0, rot = 0;
if(nums.length < 1) return -1;
int start = 0, end = nums.length-1;
while(start <= end){
int mid = (start+end)/2;
if(nums[mid] == target) return mid;
else if(nums[mid] >= nums[start]){
if(nums[mid] > target && target >= nums[start]){
end = mid - 1;
}
else{
start = mid + 1;
}
}
else{
if(nums[mid] < target && target <= nums[end]){
start = mid + 1;
}
else{
end = mid - 1;
}
}
}
return -1;
}
}
题目:有重复怎么办?
思路:在33题基础上,判断start等于mid时,只能start++遍历移动,因为此时无法判断旋转点在前半段还是后半段。
public class Solution {
public boolean search(int[] nums, int target) {
int ret = 0;
if(nums.length < 1) return false;
int start = 0, end = nums.length-1;
while(start <= end){
int mid = (start+end)/2;
if(nums[mid] == target) return true;
else if(nums[mid] > nums[start]){
if(nums[mid] > target && target >= nums[start]){
end = mid - 1;
}
else{
start = mid + 1;
}
}
else if(nums[mid] < nums[start]){
if(nums[mid] < target && target <= nums[end]){
start = mid + 1;
}
else{
end = mid - 1;
}
}
else{
start++;
}
}
return false;
}
}
题目:在一个旋转数组中找到最小值。
思路:二分法——利用二分法将start和end卡在正好反转的两端,由此只需判断mid与其前后数的关系就可以找到正好旋转的那一点,即找到最小值。
public class Solution {
public int findMin(int[] nums) {
if(nums.length < 2) return nums[0];
int start = 0, end = nums.length-1;
while(start <= end){
int mid = (start+end)/2;
if(mid > 0 && nums[mid] <= nums[mid-1]) return nums[mid];
if(mid < nums.length-1 && nums[mid] >= nums[mid+1]) return nums[mid+1];
else if(nums[mid] >= nums[start]){
start = mid+1;
}
else{
end = mid-1;
}
}
return nums[0];
}
}
34. Search for a Range
题目:在数组中找到目标值的范围,没有的话用【-1,-1】表示。
思路:二分法——基本的思想是先用二分找到目标值,在分别在【start,mid】以及【mid,start】两个区间内继续利用二分找到上范围和下范围。
public class Solution {
public int[] searchRange(int[] nums, int target) {
int[] ret = new int[]{-1, -1};
if(nums.length < 1) return ret;
int start = 0, end = nums.length-1;
while(start <= end){
int mid = (start+end)/2;
if(nums[mid] == target){
int mid_cp = mid;
if(nums[start] == target) ret[0] = start;
else{
while(nums[start] <= nums[mid]){
int mid_s = (start+mid)/2;
if(nums[mid_s] == target){
mid = mid_s-1;
}
else{
start = mid_s+1;
}
}
//ret[0] = nums[start]==target?start:start+1;
ret[0] = start;
}
mid = mid_cp;
if(nums[end] == target) ret[1] = end;
else{
while(nums[end] >= nums[mid]){
int mid_e = (end+mid)/2;
if(nums[mid_e] == target){
mid = mid_e+1;
}
else{
end = mid_e-1;
}
}
//ret[1] = nums[end]==target?end:end-1;
ret[1] = end;
}
return ret;
}
else if(nums[mid] > target){
end = mid-1;
}
else{
start = mid+1;
}
}
return ret;
}
}
题目:在1到n中找到第一个坏版本。
思路:二分——很简单,但是要注意用start+(end-start)/2,不要用(start+end)/2,不然就TLE。
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int start = 1, end = n;
while(start <= end){
int mid = start + (end-start)/2;
if(isBadVersion(mid)){
end = mid - 1;
}
else{
start = mid + 1;
}
}
return start;
}
}
题目:猜数字
思路:二分——很简单
/* The guess API is defined in the parent class GuessGame.
@param num, your guess
@return -1 if my number is lower, 1 if my number is higher, otherwise return 0
int guess(int num); */
public class Solution extends GuessGame {
public int guessNumber(int n) {
int start = 1, end = n;
while(start <= end){
int mid = start + (end-start)/2;
if(guess(mid) == 0) return mid;
else if(guess(mid) == 1){
start = mid+1;
}
else{
end = mid-1;
}
}
return start;
}
}
题目:找到目标值或者应该插入的位置
思路:二分法——很简单
public class Solution {
public int searchInsert(int[] nums, int target) {
int start = 0, end = nums.length-1;
while(start <= end){
int mid = start + (end-start)/2;
if(nums[mid] == target) return mid;
else if(nums[mid] > target){
end = mid - 1;
}
else{
start = mid + 1;
}
}
return start;
}
}
41. First Missing Positive
题目:找到数组中第一个不见的正整数
思路:分三步:第一步将负数标记为0,第二步将每位非零数对应的位置上标记为负数,0则标记为该位正整数的负数。第三步统计第一个非负数的位置,返回。
public class Solution {
public int firstMissingPositive(int[] nums) {
for(int i = 0; i < nums.length; i++){
if(nums[i] < 0) nums[i] = 0;
}
for(int i = 0; i < nums.length; i++){
int x = Math.abs(nums[i]);
if(x <= nums.length && x > 0){
if(nums[x-1] == 0){
nums[x-1] = ~x+1;
}
else if(nums[x-1] > 0){
nums[x-1] = ~nums[x-1]+1;
}
}
}
for(int i = 0; i < nums.length; i++){
if(nums[i] >= 0) return i+1;
}
return nums.length+1;
}
}
其他的解法有将数通过交换放在对应位置上,最后统计如果存在不对应的就返回。