面试经典150题(96-100)

leetcode 150道题 计划花两个月时候刷完,今天(第五十五天)完成了5道(96-100)150:

96.(74. 搜索二维矩阵)题目描述:

给你一个满足下述两条属性的 m x n 整数矩阵:
每行中的整数从左到右按非严格递增顺序排列。
每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false

第一版(我是相当于给加了一个行,然后看这个target在哪一行,然后二分查找)

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int preNum=matrix[0][0];
        if(target<preNum){
            return false;
        }
        if(target==preNum){
            return true;
        }
        for(int[] nums:matrix){
            if(target>preNum&&target<=nums[nums.length-1]){
                return midSearch(nums,target);
            }
            preNum=nums[nums.length-1];
        }
        return false;
    }
    public boolean midSearch(int[] nums,int target){
        int left=0; int right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]==target){
                return true;
            }else if(nums[mid]>target){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return false;
    }
}

97.(162. 寻找峰值)题目描述:

峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

第一版(我感觉这题。。为啥要用二分啊。。我直接遍历O(n)。。没去研究二分)

class Solution {
    public int findPeakElement(int[] nums) {
        int len=nums.length;
        if(len<=1){
           return  len-1;
        }
        int preNum=nums[0];
        for(int i=1;i<len;i++){
            if(nums[i]<preNum){
                return i-1;
            }
            preNum=nums[i];
        }
        return len-1;
        
    }
}

98(33. 搜索旋转排序数组)题目描述:

整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

第一版(这题之前做过但是这次还是没弄出来有点遗憾。。看了解题一知半解。。)

class Solution {
    public int search(int[] nums, int target) {
        int left=0;int right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]==target){
                return mid;
            }else if(nums[left]<=nums[mid]){
                if(target<nums[mid]&&target>=nums[left]){
                    right=mid-1;
                }else{
                    left=mid+1;
                }
            }else{
                if(target>nums[mid]&&target<=nums[right]){
                    left=mid+1;
                }else{
                    right=mid-1;
                }
            }
        }
        return -1;
    }
}

第二版(翻了一下我之前写过的,我感觉我这个很好理解)

class Solution {
    public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]>nums[right])
            {
                left=mid+1;
            }else
            {
                right=mid;
            }
        }
        // left 为最小数的下标
        if(nums[left]>target)
            return -1;
        if(nums[nums.length-1]>=target)
        {
            right=nums.length-1;
        }else
        {
            right=left-1;
            left=0;
        }
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]>target)
            {
                right=mid-1;
            }else if(nums[mid]<target)
            {
                left=mid+1;
            }else
                return mid;
        }
        return -1;
    }
}

99.(34. 在排序数组中查找元素的第一个和最后一个位置)题目描述:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

第一版(就是找出第一个等于这个target的然后再一直向后找)

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left=0;int right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]>=target){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        if(left>=nums.length||nums[left]!=target){
            return new int[]{-1,-1};
        }
        int[] res=new int[]{left,left};
        left++;
        while(left<nums.length){
            if(nums[left]>target){
                break;
            }else if(nums[left]==target){
                res[1]=left;
            }
            left++;
        }
        return res;
    }
}

100.(153. 寻找旋转排序数组中的最小值)题目描述:

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

第一版(这个我是试了一下,但不知道原理。。二分稀里糊涂)

class Solution {
    public int findMin(int[] nums) {
        int left=0;
        int right=nums.length-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]>nums[right])
            {
                left=mid+1;
            }else
            {
                right=mid;
            }
        }
        return nums[left];
    }
}

二分这块很细节,一不小心就死循环了。。。

加油,早日跳槽!!!

你可能感兴趣的:(面试经典,150,题,面试,算法,数据结构,leetcode)