算法基础题详解,下面都是以函数体现,亲测无误,有问题可以联系博主
题1:旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称为数组的旋转。输入一个递增排序的数组的一个旋转输出旋转数组的最小值。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.
解析:
1 2 3 4 5 6 7 8 ==>3 4 5 6 7 8 1 2(indexOfmid=6,<indexOfmid有序,>indexOfmid无序)
==>7 8 1 2 3 4 5 6(indexOfmid=2 <indexOfmid无序 >indexOfmid有序)
0011111111==>1111111100
此算法不适用于mid与两头相等的例子
例:0111111==>10111111:此时应用扫描法
总结:if(indexOfmid>beigin)左侧有序,否则右侧有序
代码:
int min(int arr[],int n) {
int begin = 0;
int end = n - 1;
int min;
//考虑没有旋转这种特殊的旋转
if (arr[begin]<arr[end])
{
return arr[begin];
}
while (begin+1<end)
{
//二分法,获取中间数
int indexOfmid = begin + ((end - begin) >> 1);
//当arr[indexOfmid]>arr[begin]左侧有序,否则右侧有序
if (arr[indexOfmid]>=arr[begin])
{
begin = indexOfmid;
}
else
{
end = indexOfmid;
}
}
min = arr[end];
return min;
}
解决上面遗留的问题
//如果中间的值和两头都相等,则用扫描法实现
if ((!(arr[indexOfmid] ^ arr[begin]))&& (!(arr[indexOfmid] ^ arr[end])))
{
min = arr[begin++];
while (begin<end+1)
{
if (min>arr[begin])
{
min = arr[begin];
}
begin++;
}
return min;
}
题二:在有空字符串的有序字符串数组中查找
有个排序后的字符串数组,其中无规律散步着一些空字符串,编写一个方法,找出给定字符串(肯定不是空字符串)的索引
此题没难度,直接用二分法,但是注意空字符串是无规律分部的
代码:
int indexOf(string str[], string p, int n) {
int begin = 0;
int end = n - 1;
int indexOfmid;
while (begin <= end)
{
indexOfmid = begin + ((end - begin) >> 1);
if (str[indexOfmid]._Equal(""))
{
indexOfmid++;
//注意,千万注意,这块容易报死循环
if (indexOfmid > end)
{
return -1;
}
}
if (str[indexOfmid]._Equal§)
{
return indexOfmid;
}
else if ((str[indexOfmid]._Equal§) > 0)
{
end = indexOfmid - 1;
}
else
{
begin = indexOfmid + 1;
}
}
return -1;
}
题三:最长连续递增子序列的长度
输入:是一个部分有序的数组
输出:一个整数
例:
输入:1 9 2 5 7 3 4 6 8 0
输出:4
解释:{1 9 2 5 7 3 4 6 8 0}中最长递增子序列为{3 4 6 8}
解析:使用双指针法,下面体现了两种方式
代码:
方法一:
int maxLength(int arr[],int n) {
int length = 1;
int temp = 1;
int j,i;
for (i=0,j=i+1; j < n;)
{
//方法一:i,j同时移动
if (arr[j]>=arr[i])
{
j++;
i++;
temp++;
}
else
{
if (length<temp)
{
length = temp;
}
temp = 1;
i = j;
j++;
}
}
return length;
}
方法二:
int maxLength(int arr[],int n) {
int length = 1;
int temp = 1;
int j,i;
for (i=0,j=i+1; j < n;)
{
//方法二:I,不动,j移动
if (arr[j] > arr[j - 1])
{
j++;
}
else
{
temp = j - i;
i = j;
j++;
if (length<temp)
{
length = temp;
}
temp = 0;
}
}
return length;
}
题四:设计一个高效的求a的n次幂的算法
用for循环求所需时间为o(n),现在需要优化至o(logn)
从o(n)优化到o(logn),就是从一个个迭代,变成每次减一半
代码:
double power(double a,int n) {
//递归出口
if (n == 0)
{
return 1;
}
double res = a;
int ex = 1;
//指数每次翻倍
//可以翻
while ((ex<<1)<=n)
{
//翻倍
res *= res;
//指数翻倍
ex <<= 1;
}
//不能翻
//那要判断n-ex是不是为0,不为0,差多少,这里使用的是递归
//在做的时候发现了相似,相似用递归
return res * power(a, n - ex);
}
下面实现了,求a的n次幂 和 a的-n次幂的整合
代码:
double power(double a,int n) {
//递归出口
if (n == 0)
{
return 1;
}
int flag = n;
if (n<0)
{
n = (~n) + 1;//将n取反
}
double res = a;
int ex = 1;
//指数每次翻倍
//可以翻
while ((ex<<1)<=n)
{
//翻倍
res *= res;
//指数翻倍
ex <<= 1;
}
//不能翻
//那要判断n-ex是不是为0,不为0,差多少,这里使用的是递归
//在做的时候发现了相似,相似用递归
//正数次幂返回
if (flag>0)
{
return res * power(a, n - ex);
}
//负数次幂返回
else
{
res = 1 / res;
return res*power(a, ex+flag);
}
}