Leetcode刷题笔记——查找
33.Search in Rotated Sorted Array
题目描述:
给定一个被翻转的整型升序数组nums,数组中无重复元素,如[4,5,6,7,0,1,2
],和一个整数target。要求在被翻转过的数组中找到target的位置,若不存在,则返回-1。并且算法的时间复杂度要求为O(log n)。
自己的思路:
如果是有序数组,则使用二分查找就可以将复杂度控制在O(log n)了。所以问题集中在找到翻转中轴,即找到数组中最小值的位置。但如何在O(log n)的复杂度之下找到最小值的位置呢,这也是我被卡住的地方。
解题思路:
使用二分法查找最小值的位置,下面是具体实现的代码:
public int searchMin(int[] nums){
int left=0, right=nums.length-1;
while (left<right){
int mid = (left+right)/2;
if(nums[mid]>nums[right]) left=mid+1;
else right=mid;
}
return left;
}
这里有一点和常规的二分法查找不同,就是当nums[mid]>nums[right]时,left等于mid+1,而当nums[mid]<=nums[right]时,right是等于mid的。这是因为当nums[mid]>nums[right]时,最小值不可能在mid位置,所以左指针可以直接跳到mid+1;但当nums[mid]<=nums[right]时,最小值可能就在mid位置上,所以右指针不能条到mid-1,而是应跳到mid位。
在看了推荐解题算法的大致思路后自己尝试写的时候就是卡在了这一点上。
下面是完整的实现代码:
class Solution {
public int search(int[] nums, int target) {
int pos = -1; if(nums.length==0) return pos; if(nums[0]<nums[nums.length-1]){
return binarySearch(nums, 0, nums.length-1, target);
} int min = searchMin(nums);
//System.out.println(min); if(target<nums[0] && target>nums[nums.length-1])
return -1;
if(target==nums[0]) return 0;
if(target==nums[nums.length-1]) return nums.length-1;
if(target>nums[0]){
pos = binarySearch(nums,0,min-1, target);
}else {
pos = binarySearch(nums,min,nums.length-1, target);
}
return pos;
} /**
* 用二分法在升序或降序数组中寻找target
* @param nums
* @param start
* @param end
* @param target
* @return
*/
public int binarySearch(int[] nums, int start, int end, int target){
while (start<=end){
int mid = (start+end)/2;
if(target == nums[mid]) return mid; if(nums[mid]>target) end=mid-1;
else start=mid+1; }
return -1;
}
/**
* 找出数组nums中最小值的位置
* @param nums
* @return
*/
public int searchMin(int[] nums){
int left=0, right=nums.length-1;
while (left<right){
int mid = (left+right)/2;
if(nums[mid]>nums[right]) left=mid+1;
else right=mid;
}
return left;
}
}
81.搜索旋转排序数组 ||
题目描述:
和上题一样,只是数组nums中的元素可以重复。
解题思路:
不知道怎么做,直接看的(能看明白的= =)题解。思路是直接使用改进的二分法查找。
二分查找的思想是不断对半缩小target所处的范围,但是当数组被翻转时,数组就不是完全有序了,此时要使用二分查找的话,需要在nums[mid]和target的比较之前明确mid位于翻转点的左侧还是右侧。如果mid位于翻转点的左侧,则mid左侧的数组是有序的,可以判断target是否在nums[start]和nums[mid]之间,若是,则end=mid-1,若非,start=mid+1;若mid位于翻转点的右侧,则mid右侧的数组是完全有序的,此时可以判断target是否在nums[mid]和nums[end]之间,若是,start=mid+1,若非,end=mid-1。
下面是完整的代码:
public boolean search_2(int[] nums, int target){
int start=0, end=nums.length-1, mid;
while (start<=end){
mid = (start+end)/2; if(nums[mid] == target) return true; //重要!!以防碰到{1,3,1,1,1,1}这种情况
while (start<=end && nums[start] == nums[end] && nums[start] == nums[mid]){
start++;
end--;
}
if(start>end) return false; //mid在旋转点左边
if(nums[mid] >= nums[start]){
//target小于mid
if(target<nums[mid] && target>=nums[start])
end = mid-1;
//target大于mid
else
start = mid+1;
} //mid在旋转点右边
else {
System.out.println(end);
//target大于mid
if(target>nums[mid] && target<=nums[end])
start = mid+1;
else
end = mid-1;
}
}
return false;
}
O(log n)理解:
对时间复杂度的推导有一点不是很明白,就是log n的复杂度是怎么回事。下面这个场景可以帮助理解,可以理解为不断地取1/2,所以折半查找算法的时间复杂度就是O(log n)。
场景:给小灰一条长16寸的面包,小灰每5天吃掉面包剩余长度的一半,第一次吃掉8寸,第二次吃掉4寸,第三次吃掉2寸......那么小灰把面包吃得只剩下1寸,需要多少天呢?
这个问题翻译一下,就是数字16不断地除以2,除几次以后的结果等于1?这里要涉及到数学当中的对数,以2位底,16的对数,可以简写为log16。
因此,把面包吃得只剩下1寸,需要 5 X log16 = 5 X 4 = 20 天。
如果面包的长度是 N 寸呢?
需要 5 X logn = 5logn天,记作 T(n) = 5logn。
Leetcode刷题笔记——查找的更多相关文章
- LeetCode刷题笔记和想法(C++)
主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...
- C#LeetCode刷题-二分查找
二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...
- 18.9.10 LeetCode刷题笔记
本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...
- LeetCode刷题笔记 - 12. 整数转罗马数字
学好算法很重要,然后要学好算法,大量的练习是必不可少的,LeetCode是我经常去的一个刷题网站,上面的题目非常详细,各个标签的题目都有,可以整体练习,本公众号后续会带大家做一做上面的算法题. 官方链 ...
- Leetcode刷题笔记(双指针)
1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...
- LeetCode刷题笔记(1-9)
LeetCode1-9 本文更多是作为一个习题笔记,没有太多讲解 1.两数之和 题目请点击链接 ↑ 最先想到暴力解法,直接双循环,但是这样复杂度为n平方 public int[] twoSum(int ...
- leetcode刷题笔记
(1)Best Time to Buy and Sell Stock Total Accepted: 10430 Total Submissions: 33800My Submissions Say ...
- leetcode刷题笔记08 字符串转整数 (atoi)
题目描述 实现 atoi,将字符串转为整数. 在找到第一个非空字符之前,需要移除掉字符串中的空格字符.如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即 ...
- LeetCode刷题笔记(1)常用知识点
1.Integer.parseInt(String s, int radix)方法的作用是:将radix进制的字符串s转化成10进制的int型数字并返回. Integer.valueof(String ...
随机推荐
- BZOJ——T 1801: [Ahoi2009]chess 中国象棋
http://www.lydsy.com/JudgeOnline/problem.php?id=1801 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: ...
- Linux vim 入门 配置 及 使用初步
网上能够找到的,关于VI的教程,更是多为能吓死人的上百页说明.事实上, 从我个人的实践看,全然不须要如此夸张.要完毕最主要的编辑.仅仅要熟悉几个命令,就是把VIM用得非常好. 这里就列举一下: Esc ...
- HDU 5502
枚举所有的最大值盒子里糖果为K的情况,对于位置p,dp[p]为p以前的,第p个操作为抽到不是蓝球里的情况,盒子里最多糖果为k的情况的概率.而到p这个位置,可以有连续最多k-1(因为第k个操作必须为抽到 ...
- POJ 2960
也算是一道模板题吧,只需按照SG函数的定义求出每个值的SG,然后异或就可以了. #include <iostream> #include <cstdio> #include & ...
- SQL 用户定义表类型,在存储过程里使用数据类型作參数
在数据库编程里使用数据类型,能够提高代码的重用性.它们常常被使用在方法和存储过程中.使用数据类型,我们能够避免在存储过程里定义一串的參数,让人眼花缭乱,它就相当于面向对象语言里.向一个方法里传入一个对 ...
- UIScrollView滚动时隐藏底部导航栏问题
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { NSLog(@"開始滚动"); int currentPostio ...
- UVa 263 - Number Chains
题目:给你一个数字n0.将它的每一个位的数字按递增排序生成数a,按递减排序生成数b, 新的数字为n1 = a-b,下次依照相同方法计算n1,知道出现循环,问计算了多少次. 分析:数论.模拟.直接模拟计 ...
- ZOJ 3814 Sawtooth Puzzle (2014年牡丹江赛区网络赛F题)
1.题目描写叙述:点击打开链接 2.解题思路:本题是一道隐式图的搜索题目.一般来说,这类题目首先要定义状态,接下来是弄清楚状态怎样转移,以及状态怎样判重,怎样推断当前状态是否和目标状态同样.至于求解最 ...
- Android+Jquery Mobile学习系列(6)-个人信息设置
本节开始,进行代码的实战练习.我的这个App是管理保险客户信息的,数据采用Sqlite存储在本地手机上,第一次使用需要先登记自己的个人信息,这个功能非常简单,也无关紧要,我是拿这个练手,方便做后面复杂 ...
- maven变量
一.pom文件,maven内置变量 ${basedir} 项目根目录 ${project.build.directory} 构建目录,缺省为target ${project.build.outputD ...