1,复杂度和简单排序算法【p2-p3】

复杂度和简单排序算法

  • 1,时间复杂度
    • 1.1选择排序
    • 1.2冒泡排序
    • 1.3异或运算
      • 1.3.1性质:
      • 1.3.2案例
        • 例1
        • 例2
    • 1.4插入排序
    • 1.5二分法
      • 1.5.1在一个有序数组中,找某个数是否存在
      • 1.5.2在一个有序数组中,找>=某个数最左侧的位置
      • 1.5.3局部最小值问题
    • 1.6对数器的概念和使用
    • 1.7递归方法和master公式
      • 1.7.1递归方法
      • 1.7.2master公式

1,时间复杂度

请添加图片描述
常数时间操作:加减乘除等少量运算
时间复杂度:在常数操作数量级的表达式中,不要低阶项,只要高阶项,而且忽略系数
大O算法时间复杂度
100N2+90万N:他的时间复杂度为O(N2)
时间复杂度按最差情况估计

1.1选择排序

时间复杂度O(N ^ 2),额外空间复杂度O(1)

#include<iostream> 
#include<algorithm>
using namespace std;
void selectSort(int arr[], int n) 
{for (int i = 0; i < n; i++) {//寻找[i,n)区间里的最小值 int minIndex = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]){minIndex = j;//更新索引		 }}//找到最小位置的索引,然后交换最小位置的数和当前的位置的数swap(arr[i], arr[minIndex]);}
}
int main() {int a[10] = { 10,15,20,1,2,3,6,45,21,22 };selectSort(a, 10);for (int i = 0; i < 10; i++){cout << a[i] << " ";}cout << endl;return 0;
}

1.2冒泡排序

时间复杂度O(N ^ 2),额外空间复杂度O(1)

#include <iostream>
using namespace std;
int main()
{int arr[10] = { 10,50,40,60,80,20,30,70,0,90 };int length = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < length - 1; i++){for (int j = 0; j < length - i - 1; j++){if (arr[j] > arr[j + 1]){swap(arr[j], arr[j + 1]);}}}for (int i = 0; i < length; i++){cout << arr[i] << " ";}cout << endl;system("pause");return 0;
}

1.3异或运算

相同为0,不同为1
请添加图片描述

1.3.1性质:

0 ^ N == N
N ^ N == 0
异或运算满足交换律和结合律
a ^ b=b ^ a
a ^ b ^ c=a ^ (b ^ c)
一堆数和一个值异或时和顺序无关,无论顺序如何结果是一样的

a=甲,b=乙
a=a ^ b; //a = 甲 ^ 乙 // b = 乙
b=a ^ b; //a = 甲 ^ 乙 // b = 甲 ^ 乙 ^ 乙 = 甲
a=a ^ b; //a = 甲 ^ 乙 ^ 甲 = 乙 // b = 甲

交换时可以不用额外申请一个空间
注意:使用的前提是两个对象在内存里是俩块独立的区域
例:下列代码中的j和j+1位置不可以在同一个位置,否则会清0这块内存

#include <iostream>
using namespace std;
int main()
{int arr[10] = { 10,50,40,60,80,20,30,70,0,90 };int length = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < length - 1; i++){for (int j = 0; j < length - i - 1; j++){if (arr[j] > arr[j + 1]){arr[j] = arr[j] ^ arr[j + 1];arr[j + 1] = arr[j] ^ arr[j + 1];arr[j] = arr[j] ^ arr[j + 1];}}}for (int i = 0; i < length; i++){cout << arr[i] << " ";}cout << endl;system("pause");return 0;
}

1.3.2案例

例1

已知一种数出现奇数次,其他数出现偶数次,怎么找到出现奇数次的数
限定:时间复杂度O(N)、空间复杂度O(1)
答:用一个变量int eor=0
把eor从第一个数异或到最后一个数,最后eor为这个出现奇数次的数
请添加图片描述

例2

已知两种数出现奇数次,其他数出现偶数次,怎么找到出现这两种数
限定:时间复杂度O(N)、空间复杂度O(1)
空间复杂度O(1)代表不会开辟新空间
答:用一个变量int eor=0,设出现奇数次的数为a和b,其他都为出现偶数次的数
用eor从第一个数异或到最后一个数,最后eor=a ^ b
因为是两种数,所以a!=b,所以eor!=0
再准备一个变量int eor‘=0,用eor’从第一个数异或到eor异或中偶数位上进行异或后不为0的整数(不存在异或状态),所以eor‘=a or b
所以a or b的另一个数=eor ^ eor’

#include <iostream>
#include <vector>std::vector<int> findOddOccurrences(std::vector<int>& nums) {int eor = 0; // 用于存储最终结果 a ^ bfor (int num : nums) {eor ^= num; // 求异或}// 找到 a 和 b 不相同的位int rightmostBit = eor & (-eor);int eor1 = 0;for (int num : nums) {if ((num & rightmostBit) != 0) {eor1 ^= num;}}int eor2 = eor ^ eor1;return { eor1, eor2 };
}int main() {std::vector<int> nums = { 2, 2, 4, 4, 5, 5, 3, 6, 6, 7 };std::vector<int> result = findOddOccurrences(nums);std::cout << "Numbers that appear odd number of times: " << result[0] << " and " << result[1] << std::endl;return 0;
}

方法二
用一个变量int eor=0,设出现奇数次的数为a和b,其他都为出现偶数次的数
用eor从第一个数异或到最后一个数,最后eor=a ^ b
因为是两种数,所以a!=b,所以eor!=0
eor&(~eor+1)提取出最右边的1
请添加图片描述

1.4插入排序

7,6,5,4,3,2,1
最多排序次数1+2+3+4+5+6
时间复杂度O(N ^ 2),额外空间复杂度O(1)
1,2,3,4,5,6,7
最少排序次数0
时间复杂度按最差情况估计

arr[] = {3,2,5,4,2,3,3}
0到0号位变为有序
3和3比较,3
0到1号位变为有序
2和3比较,3大,2,3
2和自己比较,停
0到2号位变为有序
5和3比较,5大,2,3,5
0到3号位变为有序
4和5比较,5大,2,3,4,5
4和3比较,4大,停
0到4号位变为有序
2和5比较,5大,2,3,4,2,5
2和4比较,4大,2,3,2,4,5
2和3比较,3大,2,2,3,4,5
2和2比较,相同,停
0到5号位变为有序
3和5比较,5大,2,2,3,4,3,5
3和4比较,4大,2,2,3,3,4,5
3和3比较,相同,停
…………

#include <iostream>
void test01()
{int arr[] = { 3,2,5,4,2,3,3 };int length = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < length ; i++){for (int j = i; j >0; j--){if (arr[j] < arr[j-1]){arr[j] = arr[j] ^ arr[j-1];arr[j-1] = arr[j] ^ arr[j-1];arr[j] = arr[j] ^ arr[j-1];}else{break;}}}for (int q = 0; q < length; q++){std::cout << arr[q] << " ";}std::cout << std::endl;
}int main() 
{test01();return 0;
}

1.5二分法

时间复杂度O(log2N)(logN就是log2N),log3N

1.5.1在一个有序数组中,找某个数是否存在

从小到大的有序数组,找num
如果采用遍历,时间复杂度为O(N)
二分法为O(log2N)(logN就是log2N
先找到中点x,如果x>num则找左侧继续二分,如果x<num则找右侧继续二分

1.5.2在一个有序数组中,找>=某个数最左侧的位置

1.5.3局部最小值问题

arr中无序,相邻两数一定不相等
在0位置a,1位置b,a<b则a为局部最小
在end位置a,end-1位置b,b<a则b为局部最小
在N位置,N+1和N-1位置都比N大,则N为局部最小
找到一个局部最小数,时间复杂度好于O(N)与否?

先看0和1,N-2和N-1位置看大小,0或N-1小就直接输出了
0比1大,N-1比N-2大,那么0到N-1必定存在至少一个拐点
取中点M,看M-1和M-2位置比大小,如果最小直接输出
如果不是最小,那么比M小的一侧必有拐点,
一边小则在小的一边继续二分
两边小则随机取一边继续二分

体现了两种优化,数据状况,问题标准

1.6对数器的概念和使用

有一个想要测的方法a
实现复杂度不好但是容易实现的方法b
实现一个随机样本产生器
把方法a和方法b跑相同的随机样本,看看得到的结果是否一样
如果有一个随机样本使得对比结果不一致,打印样本进行人工干预,改对方法a或者方法b
当样本数量很多时比对测试依然正确,可以确定方法a已经正确

c++随机样本产生器
int randroom=rand()%999+2;
生成0+2到998+2的数值

// 对数器.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>using namespace std;//有一个你想要测试的算法,这里以归并排序为例
class Solution {
public:static int reversePairs(vector<int>& nums) {auto L = 0;auto R = nums.size() - 1;auto res = 0;mergesort(nums, L, R);return res;}//归并排序,从大到小排列(逆序)static void mergesort(vector<int>& nums, int L, int R){//递归终止条件if (L >= R){return;}//序列中心位置计算auto mid = (L + ((R - L) >> 1));//auto mid = (R + L) / 2;//左右序列分别排序mergesort(nums, L, mid);mergesort(nums, mid + 1, R);//归并两个排好序的序列merge(nums, L, mid, R);}static void merge(vector<int>& nums, int L, int mid, int R){//临时向量存储归并的结果vector<int> tmp(R - L + 1);auto pos = 0;auto Lp = L;auto Rp = mid + 1;while ((Lp <= mid) && (Rp <= R)){tmp[pos++] = (nums[Lp] < nums[Rp]) ? nums[Lp++] : nums[Rp++];}while (Lp <= mid){tmp[pos++] = nums[Lp++];}while (Rp <= R){tmp[pos++] = nums[Rp++];}//将排序好部分拷贝至nums数组copy(nums, tmp, L, R);//nums = tmp;}//部分数组拷贝函数static void copy(vector<int>& nums, vector<int>& tmp, int L, int R){auto pos = 0;for (auto i = L; i <= R; i++){nums[i] = tmp[pos++];}}
};//准备一个随机数组(样本)生成器
//函数名:generateRandomVector
//函数功能描述:随机数组(样本)生成器
//函数参数: size    生成数组最大尺寸
//         value   数组每个元素的最大值
//返回值:  vector<int> 生成的数组
//for test
vector<int> generateRandomVector(int size, int value)
{//time 函数返回从 1970 年 1 月 1 日午夜开始到现在逝去的秒数,因此每次运行程序时,它都将提供不同的种子值。srand((int)time(NULL));//为随机数生成器产生随机种子//分配随机大小的数组,产生随机数的范围公式number = (rand()%(maxValue - minValue +1)) + minValue;vector<int> result(rand() % (size + 1));for (auto i = 0; i < result.size(); i++){result[i] = rand() % (value + 1);}return result;}//大样本测试
//函数名:main
//函数功能描述:大样本测试
//函数参数: size    生成数组最大尺寸
//         value   数组每个元素的最大值
//返回值:  vector<int> 生成的数组
//for test
int main()
{auto test_time = 50000;//测试次数,设置比较大,排除特殊情况auto size = 10;//生成数组最大尺寸auto value = 30;//生成数组每个元素的最大值auto if_accept = true;//方法是否正确标志位for(auto i = 0; i < test_time; i++){//拷贝初始化,生成新的数组向量vector<int> nums(generateRandomVector(size, value));//生成两个临时数组拷贝vector<int> nums1(nums);vector<int> nums2(nums);//绝对正确方法sort(nums1.begin(), nums1.end());//自己写的方法,想要测试的算法Solution::reversePairs(nums2);//判断两个向量是否相同,vector类已经重载了比较运算符,不用自己实现,不相同说明算法不正确if(nums1 != nums2){if_accept = false;//输出结果不相等的原始向量for(auto c: nums){cout << c << " ";}break;}}//输出结果cout << (if_accept ? "nice!\n" : "false!\n");}

1.7递归方法和master公式

1.7.1递归方法

目的:
递归行为和递归行为时间复杂度的估算
怎么用递归方法找一个数组中的最大值,系统是怎么操作的

递归基(base case):确定递归应该结束的条件,通常是问题规模达到最小的情况。
递归步骤(recursive step):将原问题分解为更小的子问题,并通过递归调用来解决这些子问题。
在使用递归时需要注意处理边界条件,避免无限递归和过深的递归栈

中点mid
mid=(L+R)/2,但是万一LR太大,可能会导致溢出,使结果变为负数出错
mid=L+(R-L)/2
请添加图片描述
p(0,5)->p(0,2)->p(0,1)->p(0,0)-返回结果>p(0,1)->p(1,1)-返回结果>p(0,1)-返回结果,取消p(0,1)压栈>p(0,2)->p(2,2)-返回结果>p(0,2)-返回结果,取消p(0,2)压栈>p(0,5)->p(3,5)->p(3,4)->p(3,3)-返回结果>p(3,4)->p(4,4)-返回结果>p(3,4)-返回结果,取消p(3,4)压栈>p(3,5)->p(5,5)-返回结果>p(3,5)-返回结果,取消p(3,5)压栈>p(0,5)

1.7.2master公式

master公式
T(N)=a* T(N/b)+O(N^d)
log(b,a)>d -> 复杂度为 O(N^log(b,a))
log(b,a)=d -> 复杂度为 O(N^d *logN)
log(b,a)< d -> 复杂度为 O(N^d)

T(N)母问题的数据量是T(N)级别的有N个数据
T(N/b)子问题的规模
a为子问题调用次数
O(N^d)除去调用之外剩下的过程的时间复杂度

使用master公式 需要看子问题规模是不是等量的,等量才可以使用

三个值一旦确定即可找出时间复杂度
logba<d 的时间复杂度O(Nd)
logba>d 的时间复杂度O(N^logb a )
logba==d 的时间复杂度O(Nd * logN)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/14780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Individual household electric power consumption个人家庭用电量数据挖掘与时序预测建模

今天接到一个任务就是需要基于给定的数据集来进行数据挖掘分析相关的计算&#xff0c;并完成对未来时段内数据的预测建模&#xff0c;话不多说直接看内容。 官方数据详情介绍在这里&#xff0c;如下所示&#xff1a; 数据集中一共包含9个不同的字段&#xff0c;详情如下&#…

手把手一起实现Visual Studio 2022本地工程提交(和克隆)Gitee

1、VS2022本地工程提交Gitee 登录Gitee&#xff0c;创建空仓库&#xff0c;如图&#xff1a; 新建仓库&#xff1a; 打开Visual Studio 2022创建的工程&#xff0c;点击创建Git存储库&#xff1a; 复制Gitee仓库URL&#xff1a; 将URL填入&#xff0c;点击创建并推送&#xff…

Windows 10 安装 PostgreSQL 12.x 报错 ‘psql‘ 不是内部或外部命令 由于找不到文件libintl-9.dll等问题

目录 序言一、问题总结问题 1 psql 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。问题 2 “由于找不到文件libintl-9.dll&#xff0c;无法继续执行代码&#xff0c;重新安装程序可能会解决此问题。“1、卸载2、安装3、安装 Stack Builder &#xff08;这个可…

LeetCode.189(轮转数组)

对于轮转数组这个题&#xff0c;文章一共提供三种思路&#xff0c;对于每种思路均提供其对应代码的时间、空间复杂度。 目录 1. 创建变量来保存最后一个数&#xff0c;并将其余数组向前挪动一位 &#xff1a; 1.1 原理解析&#xff1a; 1.2 代码实现&#xff1a; 2.创建一个…

NFT和数字藏品的安全方案解析

一、NFT和数字藏品 01 NFT是什么&#xff1f; NFT 是Non-Fungible Tokens 的缩写&#xff0c;意思是不可互换的代币&#xff0c;它是相对于可互换的代币而言的。不可互换的代币也称为非同质代币。什么是可互换的代币&#xff1f;比如BTC&#xff08;比特币&#xff09;、ETH&…

前端,js , Error in created hook: TypeError ,有bug了

怎么兄弟&#xff0c;遇到bug了&#xff1f;&#xff1f;&#xff1f;你开心吗&#xff0c;哈哈哈哈

如何在MacBook上彻底删除mysql

好久以前安装过&#xff0c;但是现在配置mysql一直出错&#xff0c;索性全部删掉重新配置。 一、停止MySQL服务 首先&#xff0c;请确保 MySQL 服务器已经停止运行&#xff0c;以免影响后续的删除操作。 sudo /usr/local/mysql/support-files/mysql.server stop如果你输入之…

kotlin 编写一个简单的天气预报app(四)

编写界面来显示返回的数据 用户友好性&#xff1a;通过界面设计和用户体验优化&#xff0c;可以使天气信息更易读、易理解和易操作。有效的界面设计可以提高用户满意度并提供更好的交互体验。 增加城市名字的TextView <TextViewandroid:id"id/textViewCityName"…

Kyuubi入门简介

一、官方简介 HOME — Apache Kyuubi 二、概述 1、一个企业级数据湖探索平台 2、一个高性能的通用JDBC和SQL执行引擎 3、一个基于spark的查询引擎服务 三、优点 1、提供hiveserver2查询spark sql的能力&#xff0c;查询效率更为高效&#xff0c;首次构建连接时会持续保持连…

628. 三个数的最大乘积

628. 三个数的最大乘积 class Solution {public int maximumProduct(int[] nums) {Arrays.sort(nums); return Math.max(nums[nums.length-1]*nums[nums.length-2]*nums[nums.length-3],nums[0]*nums[1]*nums[nums.length-1]);} }

c语言位段知识详解

本篇文章带来位段相关知识详细讲解&#xff01; 如果您觉得文章不错&#xff0c;期待你的一键三连哦&#xff0c;你的鼓励是我创作的动力之源&#xff0c;让我们一起加油&#xff0c;一起奔跑&#xff0c;让我们顶峰相见&#xff01;&#xff01;&#xff01; 目录 一.什么是…

聊聊这几年的科技风口

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 数数这几年的科技风口&#xff1a;AR&#xff08;包括什么MR、VR&#xff09;、区块链(包括后来的什么web3)、元宇宙到现在的AI&#xff0c;下面逐一谈谈…

在Ail Linux中手动配置IPv6

第一步&#xff0c;登录阿里云服务器控制台&#xff0c;在“概览”页面找到对应实例&#xff0c;然后单击实例ID。 第二步&#xff0c;在“实例详情”页面中的“网络信息”栏目中&#xff0c;可以发现“IPv6 地址”中没有数据&#xff0c;然后单击“专有网络”的专有网络ID。 第…

使用IDEA打jar包的详细图文教程

1. 点击intellij idea左上角的“File”菜单 -> Project Structure 2. 点击"Artifacts" -> 绿色的"" -> “JAR” -> Empty 3. Name栏填入自定义的名字&#xff0c;Output ditectory 选择 jar 包目标目录&#xff0c;Available Elements 里右击…

QTableWidget setSortingEnable 函数使用详解

Qt助手的解释 If enable is true, enables sorting for the table and immediately trigger a call to sortByColumn() with the current sort section and order Note: Setter function for property sortingEnabled. 如果将 enable 设置为 true 那么就会立即调用 sortByColum…

使用Appuploader工具将IPA上传到App Store的最新流程和步骤

​ 苹果官方提供的工具xcode上架ipa非常复杂麻烦。用appuploader 可以在 mac 和windows 上制作管理 证书 &#xff0c;无需钥匙串工具 条件&#xff1a;1.以Windows为例&#xff0c;创建app打包ios需要的证书和描述文件 2.准备好一个苹果开发者账号&#xff08;如果没有到苹果…

matlab使用教程(5)—矩阵定义和基本运算

本博客介绍如何在 MATLAB 中创建矩阵和执行基本矩阵计算。 MATLAB 环境使用矩阵来表示包含以二维网格排列的实数或复数的变量。更广泛而言&#xff0c;数组为向量、矩阵或更高维度的数值网格。MATLAB 中的所有数组都是矩形&#xff0c;在这种意义上沿任何维度的分量向量的长度…

C++ 类和对象篇(一) 类的引入

目录 一、类的概念 二、类的引入 三、类的定义 1.定义一个类 2.struct 和 class 的区别 3.类中成员函数的声明、实现分离 四、封装及类的访问限定符 1.封装 2.类的访问限定符 五、类的作用域和生命周期 六、类的实例化 七、类存储方法 八、计算类的大小 一、类的概念 1…

大盗阿福(记忆化搜索板子)

提供核心代码&#xff1a;&#xff08;经典的记忆化搜索套路&#xff09; int dfs(int pos){if(f[pos]!-1) return f[pos];//记忆化if(pos>n) return 0;//边界&#xff0c;越界int sum0;//模板int f10,f20;f1dfs(pos1);f2dfs(pos2)w[pos];summax(f1,f2);//模板f[pos]sum;//模…

TypeScript基础篇 - TS模块

目录 模块的概念 Export 语法&#xff08;default&#xff09; Export 语法&#xff08;non-default&#xff09; import 别名 Type Export语法【TS】 模块相关配置项&#xff1a;module【tsconfig.json】 模块相关配置项&#xff1a;moduleResolution 小节总结 模块的…