模版
//二分查找public static int binarySearch(int[] arr, int target) { int left = 0; int right = arr.length - 1; while (left <= right) { int mid = (left + right) >> 1 ; if (target == arr[mid]) { return mid; } if (arr[mid] > target) { right = mid - 1; } else { left = mid + 1; } } return -1;}//左区间查找//寻找左插入位置public int getLeft(int[] nums, int target) { int left = 0; int right = nums.length - 1; while(left <= right) { int mid = (left + right) >> 1; if(nums[mid] >= target) { right = mid - 1; }else{ left = mid + 1; } } return left;}
33 搜索旋转排序数组
输入:nums = [4,5,6,7,0,1,2], target = 0输出:4
class Solution { public int search(int[] nums, int target) { int n = nums.length; if(n == 0) return -1; if(n == 1) return target==nums[0]? 0: -1; int l = 0; int r = n-1; while(l <= r) { int mid = (l+r)>>1; if(nums[mid] == target) return mid; if(nums[mid] >= nums[0]) { if(target >= nums[0] && nums[mid] > target) { r = mid -1; }else{ l = mid + 1; } }else { if(target <= nums[n-1] && nums[mid] < target) { l = mid + 1; }else { r = mid - 1; } } } return -1; }}
34 在排序数组中查找元素的第一个和最后一个位置
输入:nums = [5,7,7,8,8,10], target = 8
class Solution { int[] nums; public int[] searchRange(int[] nums, int target) { this.nums = nums; int[] arr = new int[2]; arr[0] = -1; arr[1] = -1; if(nums.length == 0){ return arr; } int res = get(target); if(res > nums.length) return arr; if(nums[res] == target ){ arr[0] = res; arr[1] = get(target+1)-1; return arr; } return arr; } public int get(int target){ int left = 0; int right = nums.length-1; while(left <= right) { int mid = (left + right) >>1; if(nums[mid] >= target) { right = mid - 1; }else{ left = mid + 1; } } return left; }}
69 X的平方根
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
class Solution {
public int mySqrt(int x) {
int left = 0;
int right = x;
int ans = -1;
while(left <= right) {
int mid = (left+right)>>1;
if((long)mid * mid <= x) {
left = mid + 1;
ans = mid;
}else {
right = mid - 1;
}
}
return ans;
}
}
153 寻找旋转数组的最小值
输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
class Solution {
public int findMin(int[] nums) {
int low = 0;
int high = nums.length - 1;
while (low < high) {
int pivot = low + (high - low) / 2;
if (nums[pivot] < nums[high]) {
high = pivot;
} else {
low = pivot + 1;
}
}
return nums[low];
}
}
162 寻找峰值
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
class Solution {
public int findPeakElement(int[] nums) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = l + ((r - l) >> 1);
if (nums[mid] < nums[mid+1]) {
l = mid + 1;
} else {
r = mid;
}
}
return l;
}
}
300 最长递增子序列
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
//dp
//dp[i] = max(dp[i], dp[j] + 1)
//dp[i]为每一位的最长递增数
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length == 0) return 0;
int[] dp = new int[nums.length];
int res = 0;
Arrays.fill(dp, 1);
for(int i = 0; i < nums.length; i++) {
for(int j = 0; j < i; j++) {
if(nums[j] < nums[i]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
}
//dp+二分
//tails记录长度为i的序列的最大值
class Solution {
public int lengthOfLIS(int[] nums) {
int[] tails = new int[nums.length];
int res = 0;
for(int num : nums) {
int i = 0, j = res;
while(i < j) {
int mid = (i + j) / 2;
if(tails[mid] < num){
i = mid + 1;
}else{
j = mid
}
}
tails[i] = num;
if(res == j) res++;
}
return res;
}
}
456 132模式
输入:nums = [3,1,4,2]
输出:true
解释:序列中有 1 个 132 模式的子序列: [1, 4, 2] 。
//单调栈
class Solution {
public boolean find132pattern(int[] nums) {
Deque<Integer> q = new ArrayDeque();
int k = Integer.MIN_VALUE;
for(int i = nums.length-1; i>=0; i--){
if(nums[i] < k) return true;
while(!q.isEmpty()&& q.peekLast() < nums[i]) {
k = q.pollLast();
}
q.addLast(nums[i]);
}
return false;
}
}