fasd
基本排序算法
冒泡排序
没什么可说的, 改进方法就是加一个标志位防止有序后重复遍历. 由于需要遍历两次, 所以时间复杂度O(N^2)
- 传送门 --> 冒泡排序
选择排序
外层从0开始默认outer是最小数的下标, 内存从outer+1位置开始遍历, 不稳定, 如{ 3, 3, 3, 2 }, 当比较最后一个4时, 是第一个3和2交换, 从而不稳定. 内外层遍历两次, 时间复杂度O(N^2)
- 传送门 --> 选择排序
插入排序
相当于打扑克排序, outer从1到N-1, inner从outer到N-1, 时间复杂度O(N^2)
插入排序选择排序冒泡排序有浪费许多比较的次数
归并排序快的是因为小范围合并为大范围时, 有序可以同过外排方式
小组和为大组时, 组内有序没有浪费, 永远是组与组之间的比较
- 传送门 --> 插入排序
希尔排序
- 传输门 --> 希尔排序
归并排序
递归把一个数字分隔为两部分, T(N) = 2*T(N/2) + O(N)
, a= 2, b = 2, N = 1, 时间复杂度O(N*logN)
, 额外空间复杂度O(N)
递归符合master公式: T(N) = a*T(N/b) + O(N^d)
时间复杂度为:
(1) log(b, a) > d --> 复杂度O(N^(log(b, a)))
(2) log(b, a) = d --> 复杂度O(N^d * logN)
(3) log(b, a) < d --> 复杂度O(N^d)
- 传送门 --> 归并排序
快排
递归公式同归并排序, 由于需要记录分隔点, 所以额外空间复杂度O(logN), 快排做不到稳定性, 因为partition过程做不到稳定
- 经典快排与数据状况有关, 这是因为分隔点选取的问题, 如{1, 2, 3, 4, 5, 6}分隔点选取最右边时每次只排序一个数字, 此时时间复杂度为O(N^2)
- 如果分隔点选取中位数, 则每次恰好可把数组划分为两部分, 时间复杂度为O(N*logN)
- 随机快排的分隔点随机选取, 把复杂度转化为与概率有关, 复杂度长期期望为O(N*logN)
- 传输门 --> 快排
堆排
大根堆结构重要两个函数heapInsert与heapify, 一个上浮, 一个是下沉, 优先级队列就是堆
建立堆的时间复杂度为O(log1) + O(log2) + O(log3) + ... + O(log(N)), 收敛域O(N)
- 算法: 插入时, 上浮, 直至没有父节点比当前节点大; 排序交换堆顶与堆未元素, 这时堆顶元素下沉, 直至当前节点比子节点都大
- 传送门 --> 堆排
排序补充
- 归并排序可以做到额外空间复杂度O(1), 有难度, 相关搜索"归并排序内部缓存法"
- 快排可以做到稳定性, 有难度, 不要求掌握, 相关搜索"01 stable sort"; 快排的优势是partition过程中, 时间复杂度O(N), 空间复杂度O(1)
- 有一道题目, 奇数放在数组的左边边, 偶数放在数组右边, 要求原始的相对次数不变, 牛客练习 --> 调整数组顺序使奇数位于偶数前面
排序总结
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(N^2) | O(N) | O(N^2) | O(1) | 稳定 |
选择排序 | O(N^2) | O(N^2) | O(N^2) | O(1) | 不稳定 |
插入排序 | O(N^2) | O(N) | O(N^2) | O(1) | 稳定 |
希尔排序 | O(N*logN) ~ O(N^2) | O(N^1.3) | O(N^2) | O(1) | 不稳定 |
堆排序 | O(N*logN) | O(N*logN) | O(N*logN) | O(1) | 不稳定 |
归并排序 | O(N*logN) | O(N*logN) | O(N*logN) | O(N) | 稳定 |
快排 | O(N*logN) | O(N * logN) | O(N^2) | O(logN) ~ O(N) | 不稳定 |
工程中的综合排序算法
基础类型很长时, 使用快排, 因为基础数据类型不要求稳定
复合数据类型长度很长时, 使用归并排序, 复合数据类型要求稳定
任何数据类型的数组长度很短(<60)时, 使用插入排序
桶排序
桶排序是一个逻辑概念, 具体实现方法是计算排序, 基数排序
- 非基于比较的排序, 与被排序的样本的实际数据状况有很大关系, 所以实际中并不经常使用
- 时间复杂度O(N), 额外空间复杂度O(N)
- 稳定
计算排序
基数排序
一个有序数组A, 另一个无序数组B, 打印B中所有不在A中的数组, A数组长度为N, B数组长度为M
- 算法1: 暴力法, 时间复杂度O(N^2)
- 算法2: 遍历B数组, 使用二分法在A中查找相同元素, 时间复杂度
O(M * logN)
- 算法3: 把A数组进行排序, 排序最小时间复杂度
O(M*logM)
, 使用类似外排进行排序, 总时间复杂度O(M*logM) + O(M+N)
两个游标, p1指向A, p2指向B
(1) A[p1] < B[p2]; p1++
(2) A[p1] == B[p2]; p1不移动, 移动p2, 因为B数组中可能有重复数字所以只移动p2
(3) A[p1] > B[p2]; 打印并移动p2 - 传送门 --> 时间复杂度理解
使用递归查找数组中的最大值
- 算法: 二分法查找分隔数字, 返回左右数组中的最大值
本算法中T(N) = 2*T(N/2) + O(1)
, a=b=2, d=0, log(2, 2)=1 > d=0, 复杂度为O(N^log(2, 2))=O(N) - 传送门 --> 使用递归查找最大值
小和
在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和. 求一个数字的小和. 如[1, 3, 4, 2, 5]小和为16
- 算法: 利用归并排序, 关键步骤
res += (arr[lowPtr] < arr[hightPtr] ? arr[lowPtr] * (right - hightPtr + 1) : 0);
其中arr[lowPtr] * (right - hightPtr + 1)
是关键, 和归并排序一样, 没有浪费之前的比较次数
本题递归公式T(N) = 2*T(N/2) + O(N)
, 时间复杂度同归并排序, 同位O(N*logN) - 传送门 --> 小和
逆序对
在一个数组中, 左边的数如果比右边的数大, 则这两个数构成一个逆序对, 请打印所有逆序对
- 算法: 与小和相同, 只是在merge时把数组从大到小排列, 关键步骤
res += (vt[leftPtr] > vt[rightPtr] ? (right - rightPtr + 1) : 0);
与上述相差大小号和乘一个数区别, 目前只能统计个数, 打印有些问题 - 传送门 --> 逆序对
- 牛客练习 --> 数组中的逆序对
荷兰国旗问题
给定一个数组arr, 和一个数num, 请把小于num的数放在数组的左边, 等于num的数放在数组的中间, 大于num的数放在数组的右边, 要求额外空间复杂度O(1), 时间复杂度O(N)
- 算法: 准备三个游标leftPtr初始指向数组边界起始位置前一个元素即left-1, rightPtr初始指向末尾后一个元素right+1, index从头到尾遍历数组比较
(1) 比num小, index指向元素和leftPtr指向的下一元素交换, index和leftPtr同时+1
(2) 等于num, 只把index+1
(3) 大于num, 把index元素和rightPtr指向的元素前一个交换, rightPtr-1, 由于不确定rightPtr指向元素和num的关系, index不变 - 传输门 --> 荷兰国旗问题
数据流的中位数
实质利用堆排序找中位数
- 算法: 实质是利用堆
- 牛客练习 --> 数据流中的中位数
排序数组最大差值
给定一个数组, 求排序之后相邻两数的最大差值, 要求时间复杂度O(N), 且要求使用非基于比较的排序
- 算法: 运用桶的概念. N个数, 准备N+1个桶, 最小值放0号桶, 最大桶放N号桶放N号桶;
三个数组, 分别记录桶是否有值, 桶内最大值, 桶内最小值; 相邻两个数最大差值可能存在于两个非空桶之间, 也可能存在于空桶之间 - 传输门 --> 排序数组最大差值
数据流中位数
如何可以得到数据流中排序后的中位数
用数组结构实现大小固定栈
- 传输门 --> 数组实现大小固定的栈
用数组结构实现大小固定队列
- 算法: 使用三个变量: start, end, size. 目的是为了是start和end解耦合, 使start只与size有关, end只与size有关.
插入只与m_size和m_arraySize有关, 弹出只与m_size和0有关; 弹出直接弹出m_start位置的元素, 插入直接插入到m_end位置
m_start的变化只与m_arraySize有关; m_end的变化只与m_arraySize有关. m_start与m_end都是+1递增 - 传输门 --> 数组实现大小固定的队列
仅用队列结构实现栈结构
传送门 -->
仅用栈结构实现队列结构
双栈返回最小值
实现一个特殊的栈, 在实现栈的基本功能的基础上, 再实现返回栈中的最小元素的操作. 要求: 1. pop, push, getMin操作的时间复杂度都是O(1); 2. 设计的栈类型可以使用现成的栈结构
顺时针打印矩阵
给定一个整型矩阵matrix, 按照从外向里以顺时针的顺序依次打印出每一个数字. 例如:如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
旋转正方形
给定一个整型正方形矩阵matrix, 把该矩阵调整成顺时针转换90度的样子. 额外空间复杂度O(1)
- 算法: 同顺时针打印矩阵一样, 抽象一个顺时针打印边框的函数, 从外到内依次调用这个函数.
- 传送门 --> 旋转正方形矩阵
之字形打印矩阵
给定一个矩阵matrix, 按照"之"字形方式打印这个矩阵
- 算法: 抽象一个打印斜行的矩阵, 通过一个布尔变量来判断从上到下还是从下到上, 调用函数多了些边界判断. x_1和y_1, x_2和y_2先后移动次序有很大关系, 先比较x_1再判断y_1, 先比较y_2再判断x_2,
- 传输门 --> 之字形打印矩阵
行列有序的矩阵中查找
给定一个由N*M的整数型矩阵matrix和一个整数K, matrix的每一行和每一列都是排好序的. 实现一个函数, 判断K是否在matrix中. 要求时间复杂度O(N+M), 额外空间复杂度O(1)
- 算法: 从矩阵的特性出发, 确定查找方法. 设置查找起始点设置为右上角
若K小于右上角的数, 则不可能在当前列的下面, 左移起始点
若K大于右上角的数, 则不可能在当前行的左边, 下移起始点 - 传送门 --> 行列有序的矩阵中查找
- 牛客练习 --> 二维数组中的查找
链表面试与笔试
链表问题往往在空间复杂度上下工夫, 时间复杂度基本是O(N)或O(N^2)
笔试: 目的最快把问题过掉, 不追求空间复杂度
面试: 和面试官聊空间复杂度
分别实现反转单向链表和反转双向链表函数
- 算法: 分别定义两个指针, next和pre, 当head不为空时, next和pre都初始化为nullptr
(1)next指向head下一节点
(2)利用pre与head反转单/双链表
(3)使pre指向head
(4)使head指向next - 递归反转单链表:
(1)递归到最后一个节点, 然后依次返回
(2)当前节点的下一节点的next指向当前节点
(3)当前节点的next域指向nullptr - 传送门 --> 反转单双链表
- 牛客练习 --> 反转链表
判断一个链表是否是回文结构
给定一个链表的头结点head, 判断该链表是否是会问结构. 如: 1, 2, 1返回true; 1, 2, 2, 1返回true; 1, 2, 3返回false. 如果求时间复杂度O(N), 额外空间复杂度O(1)
- 算法1: 使用栈把元素逆序, 遍历两次列表, 第一次压栈, 第二次和栈中元素对比是否相同, 时间复杂度O(N), 空间复杂度O(N)
- 算法2: 使用快慢指针
单向链表划分
将单向链表按某值划分成左边小, 中间相等, 右边大的形式
复制含有随机指针节点的链表
两个连续相交问题
给定三角形ABC和一点P(x,y,z),判断点P是否在ABC内,给出思路并手写代码
- 面积计算公式及浮点数的比较
#include <iostream>
#include <math.h>
using namespace std;
#define ABS_FLOAT_0 0.0001 // 浮点数比较
struct point_float {
float x;
float y;
};
float GetTriangleSquar(const point_float pt0, const point_float pt1, const point_float pt2) {
point_float AB, BC;
AB.x = pt1.x - pt0.x;
AB.y = pt1.y - pt0.y;
BC.x = pt2.x - pt1.x;
BC.y = pt2.y - pt1.y;
return fabs((AB.x * BC.y - AB.y * BC.x)) / 2.0f;
}
bool IsInTriangle(const point_float A, const point_float B, const point_float C, const point_float D){
float SABC, SADB, SBDC, SADC;
SABC = GetTriangleSquar(A, B, C);
SADB = GetTriangleSquar(A, D, B);
SBDC = GetTriangleSquar(B, D, C);
SADC = GetTriangleSquar(A, D, C);
float SumSuqar = SADB + SBDC + SADC;
if ((-ABS_FLOAT_0 < (SABC - SumSuqar)) && ((SABC - SumSuqar) < ABS_FLOAT_0))
return true;
else
return false;
}
n个整数的无序数组,找到每个元素后面比它大的第一个数,要求时间复杂度为O(N)
vector<int> findMax(vector<int>num)
{
if(num.size()==0)return num;
vector<int>res(num.size());
int i=0;
stack<int>s;
while(i<num.size())
{
if(s.empty()||num[s.top()]>=num[i])
{
s.push(i++);
}
else
{
res[s.top()]=num[i];
s.pop();
}
}
while(!s.empty())
{
res[s.top()]=INT_MAX;
s.pop();
}
for(int i=0; i<res.size(); i++)
cout<<res[i]<<endl;
return res;
}
fasd的更多相关文章
- Quora的技术探索(转)
原文:http://www.cnblogs.com/xiekeli/archive/2012/04/27/2473808.html 关于问答类的应用,最早接触的是stackoverflow和知乎 ,而 ...
- springmvc(六)——视图和视图解析器
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoIAAAGrCAIAAADb2WEhAAAgAElEQVR4nOzdaVhTd78vfF8/z772c9 ...
- php基础知识【函数】(1)数组array
一.排序 1.sort -- 从最低到最高排序,删除原有的键名,赋予新的键名[字母比数字高] 2.rsort -- 逆向排序(最高到最低),删除原有的键名,赋予新的键名[字母比数字高] 3.asort ...
- 那些我希望在一开始使用 Zsh(oh-my-zsh) 时就知道的
原文地址:http://segmentfault.com/a/1190000002658335 作者:xavier 自带的插件 其实我用了 oh-my-zsh 快三个月后才知道原来他自带了很多插件没 ...
- amazeui 搜索 动态
<!doctype html> <html class="no-js"> <head> <meta charset="utf-8 ...
- 模糊搜索神器fzf
前言 fzf是目前最快的fuzzy finder.使用golang编写.结合其他工具(比如ag和fasd)可以完成非常多的工作. 让你通过输入模糊的关键词就可以定位文件或文件夹.当你的思维也习惯了模糊 ...
- Python系列之正则表达式详解
Python 正则表达式模块 (re) 简介 Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,和 Perl 脚本的正则表达式功能类似,使用 ...
- Codeforces Round #434 (Div. 2, based on Technocup 2018 Elimination Round 1)&&Codeforces 861C Did you mean...【字符串枚举,暴力】
C. Did you mean... time limit per test:1 second memory limit per test:256 megabytes input:standard i ...
- Python基础练习题100例(Python 3.x)
1:题目:有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. 程序源 ...
随机推荐
- 076 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 01 Java面向对象导学
076 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 01 Java面向对象导学 本文知识点:Java面向对象导学 说明:因为时间紧张,本人 ...
- DOS批处理中%cd%与%~dp0的区别详解
转载:https://www.jb51.net/article/105325.htm DOS批处理中%cd%与%~dp0的区别详解 Windows下批处理中%cd%和%~dp0都能用来表示当前 ...
- 头文件afx.h作用
转载:https://blog.csdn.net/OnceMonkeyG/article/details/95723290 一些定义与设置,为MFC提供最基本支持,将各种松散的东西组织起来,同时为MF ...
- 电机AB相编码器测速
控制任务 检测编码器的脉冲并测速 电路设计 图1 直流电机带减速器和编码器 图2 编码器接线定义 编码器接线定义如下 M1:电机电源接口,绿色的 GND:编码器电源负极输入口,橙色的 C1:编码器A ...
- 程序员你是如何使用Nacos作为配置中心的?
假如你使用的是spring-cloud-alibaba微服务技术栈 单个服务独有配置文件 即去除应用程序的状态,配置统一外部化管理,方便进行水平的伸缩. 集成步骤: 假如我有一个应用app-desig ...
- BeetleX之webapi使用入门
BeetleX是TCP通讯应用组件,在它之上可以扩展任何基于TCP的应用通讯功能.FastHttpApi是组件扩展的一个Http/Https/Websocket服务组件,它提供的功能丰富,包括功能有: ...
- ansible-playbook-roles目录结构
1. ansible-角色-roles目录结构 角色是基于已知文件结构自动加载某些vars_files,任务和处理程序的方法.按角色对内容进行分组还可以轻松与其他用户共享角色. ...
- git add 添加错文件如何撤销
git add 添加 多余文件 这样的错误是由于, 有的时候 可能 git add . (空格+ 点) 表示当前目录所有文件,不小心就会提交其他文件 git add 如果添加了错误的文件的话 以下是撤 ...
- FastJson解析Json,封装JavaBean对象
获取到前端的Json,后台对应封装JavaBean对象,对其解析赋值 获取到前端的json,对其进行分析 1.获取最外层前端json对应得JavaBean (1)未分析格式的json串 (2)初步格式 ...
- MeteoInfoLab脚本示例:线性拟合
MeteoInfoLab提供一个线性拟合函数linregress,参数是参与拟合的两个数据序列,返回拟合的斜率.截距和相关系数.有了上述拟合参数可以用polyval函数生成拟合数据(直线).然后可以将 ...