剑指offer自学系列(二)
题目描述:
在一个长度为n的数组里的所有数字都在0到n-1的范围内,数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次,请找出数组中任一个重复的数字,例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应输出的第一个重复的数字为2
题目分析:
如果我们采用两个变量去找重复的值,需要嵌套两个循环,最坏的情况是,末尾的两个值是重复的,这显然不是我们想要的答案,如果采用排序的方式得到有序数组,然后从头到尾检索,很容易就能找到第一个重复的值,排序我们采用快速排序,排序时间复杂度为o(nlogn),检索重复的值时间复杂度为o(n),我们也可以采用空间换时间,实现一个hash表,时间复杂度为o(n),检索数组,将值存到hash表中,如果hash表里没有出现这个值,就存到hash表中,如果出现过这个值,那就是我们想要的重复的值,每次查找需要o(1)的时间复杂度。
由于所有数字都在0到n-1的范围内,和数组下标恰好相对应,我们可以用交换的方法快速找到重复的值,以{2,3,1,0,2,5,3}为例:
首先第一个值为2,与下标为2的1交换,{1,3,2,0,2,5,3}
第二步交换后的值为1,继续与下标为1的值交换,{3,1,2,0,2,5,3}
第三步交换后的值为3,与下标为3的值交换,{0,1,2,3,2,5,3}
第四步,前四个值都有序,第五个值为2,与下标为2的值交换,而第二个值已经是2,结束
代码如下:
#include<iostream>
using namespace std; bool duplicate(int numbers[],int length,int* duplication) {
if (numbers == nullptr || length <= ) {
return false;
}
for (int i = ; i < length;++i) {
if (numbers[i]< || numbers[i]>length - )
return false;
}
for (int i = ; i < length;++i) {
while (numbers[i] != i) {
if (numbers[i] == numbers[numbers[i]]) {
*duplication = numbers[i];
return true;
}
int temp = numbers[i];
numbers[i] = numbers[temp];
numbers[temp] = temp;
}
}
} int main() {
int A[] = {,,,,,,};
int len = ;
int i = ;
int duplication;
bool results = duplicate(A, ,&duplication);
cout << results << endl;
cout << duplication << endl;
}
在写的过程中,我碰到了几个问题,算是C++基础问题,在此总结一下,我思索函数为什么要引用&duplication,直接用duplication不行嘛,尝试了一下报错,提示我这是局部变量,值传不回来的,所以通过对地址修改才能得到这个值,还有一点,我原以为会传两个值,2和3,但是return true返回后函数体部分就结束了,所以只会返回一个值,在此做笔记是为了加强自己记忆,不要再犯基础知识上的错误。
题目描述:
给定一个数组A[0,1,…,n-1],请你构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]xA[1]x…xA[i-1]xA[i+1]x…xA[n-1],要求不能使用除法
题目分析:
对于这个题目,由于要求我们不能采用除法,所以只能采用巧妙的方法计算这些数的乘积,我们首先表示B数组
B[0] = A[1]xA[2]x…xA[i-1]xA[i]x…xA[n-2]xA[n-1]
B[1] = A[0]xA[2]x…xA[i-1]xA[i]x…xA[n-2]xA[n-1]
…
B[i-1] = A[0]xA[1]x…xA[i-2]xA[i]x…xA[n-2]xA[n-1]
B[i] = A[0]xA[1]x…xA[i-1]xA[i+1]x…xA[n-2]xA[n-1]
…
B[n-2] = A[0]xA[1]…xA[i-1]xA[i]x…xA[n-3]xA[n-1]
B[n-1] = A[0]xA[1]…xA[i-1]xA[i]x…xA[n-3]xA[n-2]
为了让它们数组显得更有规律,写成矩阵如下
我们把被除的那些值用1代替即可以化除法为乘法,符合题目要求,下面是找到一种减少时间复杂度的方法,我们将表分成两部分,以1的斜对角线为分界线,上面从上到下相乘,下面从下往上乘,最后乘到一起即得到需要的值,代码如下:
#include<iostream>
#include<vector>
using namespace std; void multipy(const vector<double> A,vector<double> B) {
int lenA = A.size();
int lenB = B.size();
if (lenA == lenB && lenB > ) {
B[] = ;
for (int i = ; i < lenA; ++i) {
B[i] = A[i - ] * B[i - ];
}
double temp = ;
for (int i = lenA - ; i >= ; --i) {
temp = temp * A[i + ];
B[i] = B[i] * temp;
}
for (int i = ; i < lenA; ++i) {
cout << B[i] << endl;
}
}
} int main() {
vector<double> A = {,,,,,,};
vector<double> B = {,,,,,,};
multipy(A, B);
return ;
}
参考:
https://blog.csdn.net/qq_33278461/article/details/80144734(矩阵图片)
剑指offer自学系列(二)的更多相关文章
- 剑指offer题目系列二
本篇延续上一篇,介绍<剑指offer>第二版中的四个题目:从尾到头打印链表.用两个栈实现队列.旋转数组的最小数字.二进制中1的个数. 5.从尾到头打印链表 题目:输入一个链表的头结点,从尾 ...
- 剑指offer自学系列(三)
题目描述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变,例如{5,1,4,2 ...
- 剑指offer自学系列(一)
题目描述:输入n个整数,找出其中最小的k个数,例如,输入{4,5,1,6,2,7,3,8}这8个数字,最小的4个数字是1,2,3,4 题目分析:首先我能想到的是先对数组排序,从小到大,然后直接输出想要 ...
- 剑指offer自学系列(五)
题目描述:请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出 ...
- 剑指offer自学系列(四)
题目描述: 输入一个正整数数组,把数组里面所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个,例如输入数组{3,32,321},输出的最小数字为321323 题目分析: 如果采用穷举法,把 ...
- 剑指offer题目系列三(链表相关题目)
本篇延续上一篇剑指offer题目系列二,介绍<剑指offer>第二版中的四个题目:O(1)时间内删除链表结点.链表中倒数第k个结点.反转链表.合并两个排序的链表.同样,这些题目并非严格按照 ...
- 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 + 二叉排序树 + 最近公共祖先
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 Offer_68_1 题目描述 方法一:迭代法 由于该题的二叉树属于排序二叉树,所以相对较简单. 只需要判断两个结点是否在根节点的左右子树中 ...
- 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q ...
- 刷题-力扣-剑指 Offer II 055. 二叉搜索树迭代器
剑指 Offer II 055. 二叉搜索树迭代器 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/kTOapQ 著作权归领扣网络所有 ...
随机推荐
- vue-element-admin 引入高德地图并做海量点标记
第一步: 首先在index.html入口文件中添加引入高德地图的js,并填写自己在官网申请的key.如果没有申请不填写也是可以的. plugin:项目中如果有需要引入插件则使用没有直接去掉就行. &l ...
- MPAndroidChart柱子上的文字的颜色dataSet.setValueTextColors
版本:MPAndroidChart v3.1.0 这是个很强大的图表,不同的版本对应的API会不一样. 需求描述: 用了柱状图,但要实现这样的功能,通过不同的门店来区分不同的柱子的颜色,并且柱子上文字 ...
- 怎么在高清屏上画一条0.5px的边
怎么在高清屏上画一条0.5px的边呢?0.5px相当于高清屏物理像素的1px.这样的目的是在高清屏上看起来会更细一点,效果会更好一点,例如更细的分隔线. 理论上px的最小单位是1,但是会有几个特例,高 ...
- 解决新建maven工程没有web.xml的问题
首先确定创建maven工程时选择的打包方式为 war 创建后如图所示没有web.xml文件以及相关文件夹,错误信息:缺少web.xml文件 解决方法: 右击maven项目,找到ProjectFacet ...
- excel2003 颜色筛选问题
"excel2003中,添加辅助列,用定义名称的方法得到对应的颜色号,然后对辅助列进行排序: 颜色单元格在A列,选中B1,插入->名称->定义,输入a,下面输入公式 =get.c ...
- swift简介(东拼西凑,看看就的了)
OpenStack Object Storage(Swift)架构.原理及特性 https://yq.aliyun.com/articles/50262 原文 摘要: 简介 OpenStack Obj ...
- 【剑指Offer面试编程题】题目1390:矩形覆盖--九度OJ
题目描述: 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入 ...
- node属性
认识node的方法 1.dom.nodeChildrens 用于获取dom下的子元素节点 2.dom.nodeType 用于获取dom节点的属性.共有12种属性,实用属性3种. 元素节点=>1 ...
- [Tommas] ERP系统测试用例设计1(转)
问题: 1.如何进行ERP系统测试用例设计? 2.ERP系统测试用例设计过程? 3.ERP系统测试用例设计的方法? ERP系统本身是一种业务流程很复杂,单据报表众多,逻辑性很强的系统,质量保证方面很难 ...
- C 常用库函数memset,编译器宏定义assert
一. 总览 1.1库函数 函数名 头文件 功能 原型 说明 syslog syslog.h 记录至系统记录(日志) void syslog(int, const char *, ...) __p ...