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];
}
}
二分这块很细节,一不小心就死循环了。。。
加油,早日跳槽!!!