网站搭建环境营销型网站典型
网站搭建环境,营销型网站典型,网站界面设计需要首先做市场研究,淘客建站程序二分算法简介#xff1a; 二分查找算法只适用于数组有序的情况#xff1f;#xff08;只要数组中存在某种规律就可以用#xff09;模版#xff1a; 朴素的二分模版查找左边界的二分模版查找右边界的二分模版 朴素二分模版 while(left right){int mid left (right-l… 二分算法简介 二分查找算法只适用于数组有序的情况只要数组中存在某种规律就可以用模版 朴素的二分模版查找左边界的二分模版查找右边界的二分模版 朴素二分模版 while(left right){int mid left (right-left1)/2 ; //防止溢出if(...) left mid1;else if(...) right mid-1;else return ...;} 查找区间左端点/右端点的二分模版 二分查找
二分查找
题目解析
n个元素有序的数组找到 target并返回数组下标
算法原理 暴力解法从头到尾遍历若找到目标值返回下标否则返回-1。时间复杂度O(n)但并没有利用数组的有序性 一个数组中随机找一个数去和target进行比较做完比较之后划分出两个区域其中根据规律可以有选择性的舍去一个规律继续在另一个规律中寻找。此时该题目具有二段性我们可以用二分查找算法(这里选取二分之一是最优选择因为他的时间复杂度以及根据概率学问题是最优的) 朴素二分查找算法我们来探讨一下细节问题 循环结束的条件leftright 为什么是正确的因为我们是从暴力解法优化而来的相较于法一的逐个淘汰二分查找可以帮我们一次性淘汰一段区间的数字 时间复杂度
代码实现
class Solution {
public:
int search(vectorint nums, int target) {int left 0,right nums.size()-1;while(left right){int mid left (right-left)/2 ; //防止溢出if(nums[mid] target) left mid1;else if(nums[mid] target) right mid-1;else return mid;}return -1;
}
};在排序数组中查找元素的第一个和最后一个位置
在排序数组中查找元素的第一个和最后一个位置 题目解析
该数组为非递减序列的数组返回目标值开始和结束的位置。如果不存在返回-1注题中示例三如果是空数组为了避免造成越界访问我们要特殊处理直接返回-1
算法原理
暴力解法从前往后遍历数组一遍此时时间复杂度O(n)。朴素二分虽然可以找到目标值但是不确定该值是否是起始位置或者终点位置可能还需要向前遍历和向后遍历寻找所以极端情况下他的时间复杂度为O(n) 优化朴素二分 寻找左边界寻找左边界retLeft 表⽰左边界 retRight 表⽰右边界 我们注意到以左边界划分的两个区间的特点 左边区间[left, retLeft - 1] 都是⼩于 x 的右边区间包括左边界 [retLeft, right] 都是⼤于等于 x 的 因此关于mid的落点我们可以分为下⾯两种情况 当我们的 mid 落在 [left, retLeft - 1] 区间的时候也就是 arr[mid] target 。说明 [left, mid] 都是可以舍去的此时更新left 到 mid 1 的位置继续在 [mid 1, right] 上寻找左边界 当mid落在 [retLeft right] 的区间的时候也就是 arr[mid] target 。说明 [mid 1, right] 因为 mid 可能是最终结果不能舍去是可以舍去的此时更新 right 到 mid 的位置继续在 [left, mid] 上寻找左边界 细节处理 循环条件这里要写成leftright 。情况分析中left和right的最终归宿都是走到一起1.left和right一起向中间靠拢。2.left疯狂向右移动 3.right疯狂向左移动 这里说一下会死循环的原因当判断等号的情况时rightleft会进入第二个条件但right位置不变mid依旧是这个位置下次进入判断循环条件时会继续进入第二个此时进入死循环。 求中点操作若用第二个则mid会落在right的位置上此时如果进入第一个循环条件没问题但是进入第二个循环条件right位置没有动求出的mid还是这个位置下次进入循环条件时还是进入第二个所以会进入死循环 注意这⾥找中间元素需要向下取整。因为后续移动左右指针的时候 左指针 left mid 1 是会向后移动的因此区间是会缩⼩的右指针 right mid 可能会原地踏步⽐如如果向上取整的话如果剩下 1,2 两个元素 left 1 right 2 mid 2 。更新区间之后 leftrightmid 的值没有改变就会陷⼊死循环。因此⼀定要注意当 right mid 的时候要向下取整。 寻找右边界 我们注意到右边界的特点
左边区间包括右边界 [left, retRight] 都是⼩于等于 x 的右边区间 [retRight 1, right] 都是⼤于 x 的因此关于 mid 的落点我们可以分为下⾯两种情况 当我们的 mid 落在 [left, retRight] 区间的时候说明 [left, mid - 1] mid 不可以舍去因为有可能是最终结果都是可以舍去的此时更新 left 到 mid 的位置当 mid 落在 [retRight 1, right] 的区间的时候说明 [mid, right] 内的元素是可以舍去的此时更新 right 到 mid - 1 的位置由此就可以通过⼆分来快速寻找右边界 注意这⾥找中间元素需要向上取整。因为后续移动左右指针的时候 左指针 left mid 可能会原地踏步⽐如如果向下取整的话如果剩下 1,2 两个元素 left 1 right 2mid 1 。更新区间之后 leftrightmid 的值没有改变就会陷⼊死循环。右指针 right mid - 1 是会向前移动的因此区间是会缩⼩的因此⼀定要注意当right mid 的时候要向下取整。 代码实现
class Solution
{
public:vectorint searchRange(vectorint nums, int target) {// 处理边界情况if(nums.size() 0) return {-1, -1};int begin 0;// 1. ⼆分左端点int left 0, right nums.size() - 1;while(left right){int mid left (right - left) / 2;if(nums[mid] target) left mid 1;else right mid;}// 判断是否有结果if(nums[left] ! target) return {-1, -1};else begin left; // 标记⼀下左端点// 2. ⼆分右端点left 0, right nums.size() - 1;while(left right){int mid left (right - left 1) / 2;if(nums[mid] target) left mid;else right mid - 1;}return {begin, right};}
};X的平方根
x的平方根 题目解析
返回类型是整数类型只保留整数部分不允许使用任何内置指数函数和算符
算法原理
暴力解法从1开始遍历一个一个试。二分查找设ret是x的平方根最终结果用ret表示则ret左边的是平方后小于等于x的右边是大于x的。这时出现二段性使用二分查找 在left移动时因为left有可能是最终结果ret左边部分是小于等于的情况所以不能直接越过mid所以不能写成mid1。所以用查找区间右端点的模板 代码实现
class Solution {
public:int mySqrt(int x){if(x 1) return 0; // 处理边界情况int left 1, right x;while(left right){long long mid left (right - left 1) / 2; // 防溢出if(mid * mid x) left mid;else right mid - 1;}return left;}
}; 搜索插入位置
搜索插入位置 题目解析
如果能找到返回数字下标如果找不到返回该数字应该按照顺序插入的位置下标请必须使用时间复杂度为 O(logn) 的算法。
算法原理
二分查找
插入位置有数找到直接返回下标插入位置没数寻找出现第一个比该数大的位置或者是数组最后一个位置
综上所述插入位置ret最终应该大于等于目标值因此通过ret将数组划分为两个区间此时发现二段性用二分查找。所以我们只需要找到大于等于目标值区间的左端点即可。所以我们套用查找区间左端点的模板
当xt时最终结果一定不会在左边这个区间所以直接让leftmid1可以跳过当xt时right可能是最终结果所以不能越过mid。
代码实现
class Solution {
public:int searchInsert(vectorint nums, int target) {int left 0, right nums.size() - 1;while(left right){int mid left (right - left) / 2;if(nums[mid] target) left mid 1;else right mid;}//此时right和left已经相遇所以这里返回谁都可以if(nums[left] target) return right 1; //插入位置在数组最后一个位置return right;}
};山脉数组的峰顶索引
山脉数组的峰顶索引 题目解析
寻找峰值的下标该题是严格存在山峰数组只有一个山峰 算法原理
暴力解法从第一个开始遍历当该数字小于前一个数字则不是峰值当第一个出现大于前一个数的则是峰值。时间复杂度O(n)优化探寻性质红色箭头一侧的性质后一个数字总是大于前一个数字蓝色箭头一侧的性质后一个数总是小于前一个数。所以发现二段性用二分查找这里我们得出即使数组没有单调性也可以二分查找 当数字落在红色箭头这一列时峰值是在这一区间的右端点所以不能跳过故更新left位置时leftmid 当数字落在蓝色箭头这一列时峰值一定不会在该区域所以更新right位置时right mid-1 代码实现
class Solution {
public:int peakIndexInMountainArray(vectorint arr) {int left 1,right arr.size()-2; //这里不让left1rightarr.size()-1是因为不可能在第一个位置while(left right){int mid left(right-left1)/2;if(arr[mid] arr[mid-1]) left mid;else right mid-1;}return left;}
};寻找峰值
寻找峰值
该题严格无序数组可能出现多个山峰的情况
题目解析
峰值元素是大于左右相邻两个数峰值可能有多个返回任意一个位置的下标即可数组中不会有相邻的相同元素对于所有有效的 i 都有 nums[i] ! nums[i 1]
算法原理
暴力解法会遇到三种情形时间复杂度O(n) 从第一个位置开始走发现直接开始下降则第一个位置就是峰值从第一个位置开始现逐渐上升后下降返回下降前的峰值从第一个位置开始发现一直上升则返回最后一个位置的下标 优化总体分为两种情况 当arr[i] arr[i1]红色箭头此时左区间一定会存在峰值右区间可能会存在当arr[i] arr[i1]蓝色箭头此时右区间一定会存在峰值左区间可能会存在 故得出二段性使用二分查找。
当arr[i] arr[i1]此时左区间一定有结果(上图左区间包含i)则让right去到左区间故right mid当arr[i] arr[i1]此时右区间一定有结果右区间包含i1则让left去到右区间故right mid1 代码实现
class Solution {
public:int findPeakElement(vectorint nums) {int left 0,right nums.size()-1;while(left right){int mid left(right-left)/2;if(nums[mid] nums[mid1]) right mid;else left mid1;}return left;}
};寻找旋转排序数组中的最小值
寻找旋转排序数组中的最小值 题目解析
旋转操作将最后一个数放到最前面找出数组的最小值,返回该元素
算法原理 解法一暴力解法遍历查找最小值时间复杂度为O(n) 解法二二分查找可以把旋转后的数组分为两部分两部分都是呈现递增的形式把该问题抽象成折线图我们会发现明显的二段性我们以D点作为参照物会发现折线AB上的值全部大于D点的值折线CD上的值都小于或等于D点的值。所以我们找到C点对应的值即为最小值即可 当mid值落在AB区间时此时该区间一定不存在最小值所以在更新left到mid位置时让leftmid1当mid值落在CD区间时此时该区间存在最小值所以更新right时不能越过mid的位置让rightmid 代码实现
class Solution {
public:int findMin(vectorint nums) {int left 0,right nums.size()-1;int x nums[right]; //表示最后一个位置的值while(left right){int mid left(right-left)/2;if(nums[mid] x) left mid1;else rightmid;}return nums[left];}
};0~n-1缺失的数字
0~n-1缺失的数字 题目解析
⼀个⻓度为n-1的递增排序数组中的所有数字都是唯⼀的并且每个数字都在范围0〜n-1之内。在范围0〜n-1内的n个数字中有且只有⼀个数字不在该数组中请找出这个数字
算法原理
解法一借助容器哈希表n个数建立一个n1大小的哈希表然后向哈希表里填入填完后观察哪个位置没有填到即为确实的数字解法二直接遍历解法三位运算用异或操作将缺失的数组与正常的数组进行异或异或操作相同的数会抵消缺少的数因为没有对应的数字和它进行异或操作抵消所以最后异或的结果就是缺少的数。 解法四数学方法——高斯求和公式。先对正常数组进行求和高中的等差数列然后依次减去缺失数组的数剩下的数字即为缺失的数字
以上解法时间复杂度都是O(n)哈希表解法中还有个O(n)的空间复杂度 解法五二分查找左边区间数组下标的值与正常的数组下标一一对应右边区间数组中数字下标与正常的不是一一对应即发现该数组的二段性。我们需要找的结果就在五角星位置即右边区间最左边的位置 当mid落在左边区间时判读条件为下标值是否一一对应更新leftleftmid1当mid落在右边区间时更新right因为mid有可能在最终结果上所以不能跳过让rightmid这里还有个细节问题如下图这个数组是完全递增的数组该数组缺少的数字是4但是我们的二分查找找的是右边区间的左端点。我们发现这个数组根本不存在右区间此时二分的结果落在了3这个位置但这个位置的值并不是我们需要的结果而是该位置的后一个位置。所以最终返回的时候需要判断当最后left和right相等时此时所指的位置的值的下标与其相等说明该数组是一个完全递增的数组我们缺失的数字时left和right下一个位置。返回left1 代码实现
class Solution {
public:int takeAttendance(vectorint records) {int left 0, right records.size() - 1;while(left right){int mid left (right - left) / 2;if(records[mid] mid) left mid 1;else right mid;}//返回left和right都行//处理细节问题 return left records[left] ? left 1 : left;}
};
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/89251.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!