剑指offer数组3
面试题11:旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
考察对二分查找的理解
1. 定义两个指针。第一个 index1 指向第一个元素,第二个 index2 指向最后一个元素。
2. 数组的中间元素 indexMid。如果该中间元素位于前面的递增子数组,那么它大于等于第一个指针指向的元素(最小的元素应该在后面)。index1 = indexMid
如果中间元素位于后面的递增子数组,那么它小于等于第二个指针指向的元素(最小的元素应该在前面)index2 = indexMid
3. 最终两个指针会相邻,第二个指针指向的刚好是最小的元素
特殊情况:
数组{1,0,1,1,1}和数组{1, 1, 1, 0, 1}都看以看成递增排序数组{0, 1, 1, 1, 1}的旋转

当两个指针指向的数字及它们中间的数字三者相同,我们无法判断中间元素位于前面的子数组还是后面的子数组。不得不采用顺序查找的方法。
#include <exception>
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int size = rotateArray.size();
if(size == ){
return ;
}
int left = ,right = size - ;
int mid = ;
while(rotateArray[left] >= rotateArray[right]){
if(right - left == ){
mid = right;
break;
}
mid = left + (right - left) / ;
// rotateArray[left] rotateArray[right] rotateArray[mid]三者相等
// 无法确定中间元素是属于前面还是后面的递增子数组
// 只能顺序查找
if(rotateArray[left] == rotateArray[right] && rotateArray[left] == rotateArray[mid]){
return MinOrder(rotateArray,left,right);
}
// 中间元素位于前面的递增子数组
// 此时最小元素位于中间元素的后面
if(rotateArray[mid] >= rotateArray[left]){
left = mid;
}
// 中间元素位于后面的递增子数组
// 此时最小元素位于中间元素的前面
else{
right = mid;
}
}
return rotateArray[mid];
}
private:
// 顺序寻找最小值
int MinOrder(vector<int> &num,int left,int right){
int result = num[left];
for(int i = left + ;i < right;++i){
if(num[i] < result){
result = num[i];
}//if
}//for
return result;
}
};
面试题56:数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度为O(1)
假设输入数组{2, 4, 3, 6, 3, 2, 5, 5}。当我们依次对数组中的每个数字进行异或运算之后,得到的结果是0010。异或得到结果中的倒数第二位是1,于是我们根据数字的倒数第二位是不是1,将该数组分为两个子数组。第一个子数组{2, 3, 6, 3, 2}中所有数字的倒数第二位都是1,而第二个子数组{4, 5, 5}中所有数字的倒数第二位是0。接下来对每个子数组求异或,第一个子数组的结果是6,第二个子数组的结果是4
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int length = data.size();
if(length < )
return;
int resultExclusiveOR = ;
for(int i = ; i < length; ++i)
{
// 所有元素相异或,得到结果。本例为0010
resultExclusiveOR ^= data[i];
}
// indexOf1 为倒数第二位
unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
*num1 = *num2 = ;
for(int j = ; j < length; ++j)
{
if(IsBit1(data[j], indexOf1))
*num1 ^= data[j];
else
*num2 ^= data[j];
}
}
// 找到最右边是1的位
unsigned int FindFirstBitIs1(int num)
{
int indexBit = ;
while(((num & ) == ) && (indexBit < * sizeof(int)))
{
num = num >> ;
++indexBit;
}
return indexBit;
}
// IsBit1 是判断在num的二进制表示中从右边数起的indexBit位是不是1
bool IsBit1(int num, unsigned int indexBit)
{
num = num >> indexBit;
return (num & );
}
};
面试题57:和为s的数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
// 返回的结果是个数组
vector<int> result;
int length = array.size();
if(length <= )
return result;
int head = ;
int behind = length - ;
while(head < behind)
{
int curSum = array[head] + array[behind];
if(curSum > sum)
{
--behind;
}
else if(curSum < sum)
{
++head;
}
else
{
result.push_back(array[head]);
result.push_back(array[behind]);
break;
}
}
return result;
}
};
面试题57(二):和为s的连续正数序列
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如:输入15,由于1+2+3+4+5=7+8=15,所以打印出3个连续序列1~5、4~6和7~8
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > result;
if(sum < )
return result;
int small = ;
int big = ;
int middle = ( + sum) / ;
while(small < middle)
{
int curSum = (small + big) * (big - small + ) / ;
if(curSum < sum)
++big;
if(curSum == sum)
{
vector<int> res;
for(int i = small; i <= big; ++i)
{
res.push_back(i);
}
result.push_back(res);
++small;
}
if(curSum > sum)
{
++small;
}
}
return result;
}
};
剑指offer数组3的更多相关文章
- 剑指 Offer —— 数组中重复的数字
数组中的重复数字 题目描述 牛课网链接 长度为 n 的数组里,所有数字都在 0 到 n-1 的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一 ...
- 剑指offer 数组中重复的数
在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为7的数组{ ...
- 剑指Offer 数组中只出现一次的数字
题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路: 因为有2个数字只出现了一次,而其他的数字都是2次,可以通过异或运算,得到最后这2个只 ...
- [剑指OFFER] 数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 分析:利用归并排序的思想,分成2部分,每一部分按照从大到 ...
- 剑指offer数组2
面试题39:数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次, ...
- 剑指offer数组1
面试题3:数组中重复的数字 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例 ...
- 剑指offer数组列表
一.数组 面试题3 : 找出数组中重复的数字 面试题3(二):不修改数组找出重复的数字 面试题4:二维数组的查找 面试题21:调整数组顺序使奇数位于偶数前面 面试题39:数组中出现次数超过一半的数字 ...
- 剑指Offer——数组中重复的数字
题目描述: 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度 ...
- 剑指Offer——数组中只出现一次的数字
题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 分析: 数组中一共有偶数个数.两个数字只出现过一次. 相同数异或在一起等于0,那么将所有数异或 ...
随机推荐
- AtomicInteger学习
面试时被问到了,补下 import java.util.concurrent.atomic.AtomicInteger; /** * Created by tzq on 2018/7/15. */ p ...
- Python——电子邮件、Internet协议相关模块
一.电子邮件相关模块 email:用于处理电子邮件 smtpd:SMTP服务器 base64:Base-16.32.64数据编码 mhlib:处理MH文件格式解析的类 mailcap:mailcap文 ...
- PS中如何提高修改psd图片的效率(自动选择工具)
在photoshop中制作图片的时候,一般要养成保留psd格式的习惯,纵然普通时候jpg,png格式常用,考虑到以后可能需要修改,也应该备份一下.如果考虑到以后需要修改,可每次成品保存成两个,一个ps ...
- codeforces483B
Friends and Presents CodeForces - 483B You have two friends. You want to present each of them severa ...
- 【51NOD1965】奇怪的式子 min_25筛
题目描述 给你\(n\),求 \[ \prod_{i=1}^n{\sigma_0(i)}^{i+\mu(i)} \] 对\({10}^{12}+39\)取模. \(\sigma_0(i)\)表示约数个 ...
- css经常使用的六种文本样式
css当中经常使用的六种文本样式 css 文本样式是相对于内容进行的样式修饰,下面来说下几种常见的文本样式. 首行缩进 首行缩进是将段落的第一行缩进,这是常用的文本格式化效果.一般地,中文写作时开头空 ...
- C#动态操作DataTable(新增行、列、查询行、列等)
public void CreateTable() { //创建表 DataTable dt = new DataTable(); //1.添加列 dt.Columns.Add("Name& ...
- Linux下安装部署Samba共享盘的操作手册
简述 Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成.SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的 ...
- OS + macOS Mojave 10.14.4 / sushi / ssh-keygen / ssh-copy-id
s 系统版本: macOS 10.14.4 (18E226) 内核版本: Darwin 18.5.0 型号名称: Mac mini 2014 型号标识符: Macmini7,1 处理器名称: Inte ...
- 1.3浅谈Spring(IOC容器的实现)
这一节我们来讨论IOC容器到底做了什么. 还是借用之前的那段代码 ClassPathXmlApplicationContext app = new ClassPathXmlApplicationCon ...