4.12刷题总结

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--;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值