Binary Search

191 阅读4分钟

458. Last Position of Target 思路: 相等的时候抛弃左边

public class Solution {
    /**
     * @param nums: An integer array sorted in ascending order
     * @param target: An integer
     * @return: An integer
     */
    public int lastPosition(int[] nums, int target) {
        // write your code here
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int start = 0;
        int end = nums.length - 1;
        
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] <= target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (nums[end] == target) {
            return end;
        }
        if (nums[start] == target) {
            return start;
        }
        
        return -1;
    }
}

14. First Position of Target

  • 思路: 相等的时候抛弃右边
public class Solution {
    /**
     * @param nums: The integer array.
     * @param target: Target to find.
     * @return: The first position of target. Position starts from 0.
     */
    public int binarySearch(int[] nums, int target) {
        // write your code here
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int start = 0;
        int end = nums.length - 1;
        
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] >= target) {
                end = mid;
            } else {
                start = mid;
            }
        }
        if (nums[start] == target) {
            return start;
        }
        if (nums[end] == target) {
            return end;
        }
        
        return -1;
    }
}

28. Search a 2D Matrix

public class Solution {
    /**
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    public boolean searchMatrix(int[][] matrix, int target) {
        // write your code here
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        int start = 0;
        int rows = matrix.length;
        int cols = matrix[0].length;
        int end = rows * cols - 1;
        
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (matrix[mid / cols][mid % cols] <= target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (matrix[end / cols][end % cols] == target || matrix[start / cols][start % cols] == target) {
            return true;
        }
        
            return false;
    }
}

LeetCode. 240. Search a 2D Matrix II 思路: 左下 到 右上

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        
        int rows = matrix.length;
        int cols = matrix[0].length;
        int startRow = rows - 1;
        int startCol = 0;
        // System.out.println("startRow: " + startRow);
        // System.out.println("startCol: " + startCol);
        // 注意判断这里的越界条件
        while (startRow >= 0 && startRow < rows && startCol >= 0 && startCol < cols) {
            // System.out.println("startRow: " + startRow);
            // System.out.println("startCol: " + startCol);
            if (matrix[startRow][startCol] == target) {
                return true;
            } else if (matrix[startRow][startCol] < target) {
                startCol = startCol + 1;
            } else {
                startRow = startRow - 1;
            }
            
        }
        
        return false;
    }
}

Lint61. Search for a Range

  • 思路: First Position + Last Postion 扫两遍
public class Solution {
    /**
     * @param A: an integer sorted array
     * @param target: an integer to be inserted
     * @return: a list of length 2, [index1, index2]
     */
    public int[] searchRange(int[] nums, int target) {
        // write your code here
        if (nums == null || nums.length == 0) {
            return new int[]{-1, -1};
        }
        int[] res = new int[2];
        
        int start = 0;
        int end = nums.length - 1;
        
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] >= target) {
                end = mid;
            } else {
                start = mid;
            }
        }
        if (nums[start] == target) {
            res[0] = start;
        } else if (nums[end] == target) {
            res[0] = end;
        } else {
            return new int[]{-1, -1};
        }
        
        start = 0;
        end = nums.length - 1;
        
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] <= target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (nums[end] == target) {
            res[1] = end;
        } else if (nums[start] == target) {
            res[1] = start;
        } else {
            return new int[]{-1, -1};
        }
        
        return res;
    }
}

Lint62. Search in Rotated Sorted Array

  • 思路: 需要同时判断在哪个区间上 Last Element是标志

刚才想复杂了,其实就是在判断二分的时候,需要check target和两个端点值,而不能只是check一个值, 因为仅仅满足target > nums[start] 或 target < nums[mid] 都不能够保证舍弃右半边的所有元素 来让end = mid, 只有当

切割完成之后还是一个rotated sorted array, 可以继续二分下去

public class Solution {
    /**
     * @param A: an integer rotated sorted array
     * @param target: an integer to be searched
     * @return: an integer
     */
    public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int start = 0;
        int end = nums.length - 1;
        
        while (start + 1 < end) {
            
            int mid = start + (end - start) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            if (nums[start] < nums[mid]) {
                if (nums[start] <= target && target <= nums[mid]) {
                    end = mid;
                } else {
                    start = mid;
                }
            } else {
                if (nums[mid] <= target && target <= nums[end]) {
                    start = mid;
                } else {
                    end = mid;
                }
            }
        }
        
        if (nums[start] == target) {
            return start;
        }
        if (nums[end] == target) {
            return end;
        }
        
        return -1;
    }
}

Follow Up: 存在重复值

159. Find Minimum in Rotated Sorted Array

  • 找最小一定要有比较 nums[i] < nums[i + 1] nums[i] < nums[i - 1]
public class Solution {
    /**
     * @param nums: a rotated sorted array
     * @return: the minimum number in the array
     */
    public int findMin(int[] nums) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        
        int start = 0, end = nums.length - 1;
        int target = nums[nums.length - 1];
        
        // find the first element <= target
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] <= target) {
                end = mid;
            } else {
                start = mid;
            }
        }
        // 这里必定存在最小值,所以不需要返回 -1 
        if (nums[start] <= target) {
            return nums[start];
        } else {
            return nums[end];
        }
    }
}

Lint585.Maximum Number in Mountain Sequence

public class Solution {
    /**
     * @param nums a mountain sequence which increase firstly and then decrease
     * @return then mountain top
     */
    public int mountainSequence(int[] nums) {
        // Write your code here
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int start = 0;
        int end = nums.length - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            // 这里的OOXX的特点是 nums[mid] > nums[mid + 1] 找到第一个nums[mid] <= nums[mid + 1]的时候就停了
            if (nums[mid] > nums[mid + 1]) {
                end = mid;
            } else {
                start = mid;
            }
        }
        return Math.max(nums[start], nums[end]);
    }
}

Find Peak Element

public class Solution {
    /*
     * @param A: An integers array.
     * @return: return any of peek positions.
     */
    public int findPeak(int[] A) {
        // write your code here
     
        int start = 0;
        int end = A.length - 2;
        while(start + 1 < end){
           int mid = start + (end - start) / 2;
            //如果中间的数比后一位数大的话,peek点肯定在mid左边或是mid。
            //如果中间的数比前一位数小的话,peek点肯定在mid右边或是mid。
            if(A[mid]>A[mid + 1]){
                end = mid;
            } else {
              start = mid;  
            }
           
        }
        if(A[start] < A[end]){
            return end;
        } else {
            return start;
        }
    }
}