240.搜索二维矩阵-m
矩阵特点:每行从左至右升序,每列从上至下升序
法1:对每行进行二分查找
注意二分能取到等号:while(left <= right)
时间复杂度:O(m*logn),m为矩阵行数,n为矩阵列数,下同。
空间复杂度:O(1)
进入二分前的剪枝:target < matrix[i][left],返回false;target > matrix[i][right],continue。
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//对每一行进行二分查找
for (int i = 0; i < matrix.length; i++){
int left = 0;
int right = matrix[0].length - 1;
if(target > matrix[i][right]) continue;
if(target < matrix[i][left]) return false;
while(left <= right){//可以取等号
int mid = (left + right)/2;
if(matrix[i][mid] == target){
return true;
}else if(matrix[i][mid] < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return false;
}
}
法2:Z形查找,从右上角开始
从右上角开始,遍历元素小于目标值就往下走,否则往左走。
时间复杂度:O(m+n)
空间复杂度:O(1)
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//Z形查找,从右上角开始
int m = matrix.length;
int n = matrix[0].length;
int x = 0;
int y = n - 1;
while(x < m && y >= 0){
if(matrix[x][y] == target){
return true;
}else if(matrix[x][y] < target){//当前遍历元素小于目标值,往下走
x++;
}else{
y--;
}
}
return false;
}
}
31.下一个排序-m
类似找个下一个更大的数。
边界:数组本身升序,直接reverse即可
方法:两次扫描
第一次扫描:从后向前,找到第一个大于其右边的数,位置记为i
第二次扫描:从后向前到i+1,找到第一个大于nums[i]的数,位置记为k
如果i>=0,交换i和k的数,reverse[i+1,end)
class Solution {
public void nextPermutation(int[] nums) {
int n = nums.length;
if (n == 1) return;
int i = n - 2; //前
int j = n - 1;//后
int k = n - 1;
//1.从后向前找到第一个比其右侧小的的数,[j,end)一定是降序
while(i >= 0 && nums[i] >= nums[j]){
i--;
j--;
}
//2.不是全升序数组/最后一个排列,就从后向前在[j,end)找到第一个大于nums[i]的数
if(i >= 0){
while(nums[i] >= nums[k]){
k--;
}
swap(nums,i,k);//3.交换小数nums[i]和大数nums[k]
}
//4.如果找不到i说明数组本身降序,直接逆序即可
reverse(nums,j,n-1);
}
private void swap(int nums[], int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
private void reverse(int nums[], int i, int j){//用【双指针】把降序变为升序
while(i < j){
swap(nums, i, j);
i++;
j--;
}
}
}