三道简单算法题(二)

简介:

1:试着用最少的比较次数去寻找数组中的最大值和最小值。

思路一:扫描数组两次,第一次等到最大值,第二次等到最小值。总共比较次数2N,这是大家都可以想到的。

思路二:定义两个变量存放最大值和最小值,将数组两两分组,两两进行比较,大的和最大值进行比较,小的和最小值比较,数组两两比较次数是N/2,分别与最大值和最小值比较的次数为N,总共比较次数1.5N。好久没写算法了,于是蛋疼得想实现一下。

复制代码
//1:试着用最少的比较次数去寻找数组中的最大值和最小值。 
void FindMaxMin(int *A,int size,int* Max,int* Min)
{ 
    int i=(size & 1)?1:0;
    *Max=*Min=A[0]; 
    for(;i<size;i=i+2)
    {
        if(A[i]>A[i+1])
        {
            if(A[i]>*Max) 
                *Max=A[i]; 
            if(A[i+1]<*Min) 
                *Min=A[i+1]; 
        }else{
            if(A[i+1]>*Max) 
                *Max=A[i+1]; 
            if(A[i]<*Min) 
                *Min=A[i]; 
        }
    }  
}

void FindMaxMinTest(){
    int A[9]={2,4,6,8,9,1,3,5,7};
    int Max=0;
    int Min=0;
    FindMaxMin(A,9,&Max,&Min);
    cout<<Max<<endl;
    cout<<Min<<endl;
}
复制代码

写完之后,发现这太简单了,不过瘾,于是又实现了两题,当然这三道题的思路都很早之前就看过。

2:给一个整数数组,求数组中重复出现次数大于数组总个数一半的数

按照抵消的思路,如果存在一个数出现的次数大于数组的一半,将这个数与其他不同的数进行一一抵消,最后剩下的必定就是这个数,然后再验证这个数是否是真的出现次数超过数组的一半,实现如下,以前也实现过,但是发现这次的实现和以前的实现出入较大,这是为什么呢?

复制代码
//2:给一个整数数组,求数组中重复出现次数大于数组总个数一半的数
int MoreThanHalf(int *A,int size)
{ 
    int num=A[0];
    int count=1;
    for(int i=1;i<size;i++)
    { 
        if(num==A[i])
        {
            count++;
        }else{
            count--;  
            if(count==0)
            { 
                num=A[i];
                count=1;
            }
        } 
    }
     
    count=0;
    for(int i=0;i<size;i++)
    {
        if(A[i]==num)
            count++;
    }  
    return count>(size/2)? num:-1;
}

void MoreThanHalfTest()
{
    int A[9]={ 1, 1,2, 1, 2, 2, 1, 2, 2 };
    cout<<MoreThanHalf( A,9);
}
复制代码

 

3:给一个很大的数组,里面有两个数只出现过一次,其他数都出现过两次,把这两个数找出来

按照异或运算的思路解题。假设这两个数分别为A,B;将数组的每个元素异或运算一次,得到这两个数的异或运算结果C,因为其他的数都是两两出现,异或运算的值为0,这个结果值C的二进制位中为1的位必只有A,B其中一个数有,因为异或运算就是不同的值才能得到1,相同的为0。即1&1=0;0&0=0;1&0=1。那么我们就可以随便从结果C中取出一个二进制位为1的位与其后面的0得到一个数,若结果C的二进制位后8位为00010100,那么我们就可以得到4(二进制100),然后将数组中的每一个与4进行异或运算,这样我们就能将数组分为两组,A,B就被分到不同的组,其他的数被分到那个组并不用管,因为经过异或运算之后的值都为0,将两组分别就行以后运算之后就能得到A,B的值了,其他的数都互相抵消了。

复制代码
//3:给一个很大的数组,里面有两个数只出现过一次,其他数都出现过两次,把这两个数找出来
void FindTwoNum(int* A,int size, int* first,int* second)
{
    int excVal=A[0];
    for(int i=1;i<size;i++)
    {
        excVal^=A[i];
    }
    int s1=1;
    int s2=excVal;
    while((s2&1)==0)
    {
        s2>>=1;
        s1<<=1;
    }
    *first=excVal;
    for(int i=0;i<size;i++)
    { 
        if(s1&A[i]) 
            *first^=A[i];
    }
    *second=excVal^*first;
}

void FindTwoNumTest()
{
    int A[12]={2,1,1,2,3,3,5,7,4,4,7,9};
    int first=0,second=0;
    FindTwoNum(A,12,&first,&second);
    cout<<first<<endl;
    cout<<second;
}
复制代码

三道简单算法题(一)



本文转自啊汉博客园博客,原文链接:http://www.cnblogs.com/hlxs/archive/2013/03/28/2986191.html

目录
相关文章
|
1月前
|
存储 算法
|
6月前
|
机器学习/深度学习 算法 测试技术
青蛙跳台阶:我如何得知它是一道斐波那契数列题?——应用题破题“三板斧”(二)
这篇内容是关于解题策略的,主要介绍了在面对应用题时可以采用的“三板斧”方法:举例、模拟和找规律。通过一个走楼梯的例子详细解释了这三个步骤如何运用。首先,举例将抽象问题具体化,比如走5级台阶有几种方式。其次,通过模拟不同情况,例如思考走每一步的可能,发现递归或循环的模式。最后,通过找规律归纳出一般性的解决方案,这里发现走台阶问题与斐波那契数列相关。文章还提到了一个拓展案例——矩形覆盖问题,同样可以用类似的方法分析。总的来说,文章强调了解题过程中理解和转化问题的重要性,以及通过训练提升这方面能力。
56 0
|
6月前
|
C语言
青蛙跳台阶:我如何得知它是一道斐波那契数列题?——应用题破题“三板斧”(一)
这篇内容介绍了C语言学习中的经典例题——斐波那契数列,强调了解题思路的重要性。斐波那契数列是一个数列,其中每个数是前两个数的和。文章指出,很多类似题目,如“青蛙跳台阶”,实质上都在考察斐波那契数列的实现。文中提供了斐波那契数列的定义、代码实现和递归与非递归的思路,并鼓励读者从问题中分析出解题模型,而非直接套用已知方法。此外,还提及了一道相关题目“矩形覆盖问题”,以供进一步练习。
49 0
|
机器学习/深度学习 算法
算法提高:组合数学| 卡特兰数的实现
卡特兰数列是组合数学中在各种计数问题中常出现的数列,其前几项为1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012…… 卡特兰数首先是由欧拉在计算对凸n边形的不同的对角三角形剖分的个数问题时得到的,即在一个凸n边形中,通过不相交于n边形内部的对角线,把n边形拆分成若干三角形,不同的拆分数用Hn表示,Hn即卡特兰数。
145 0
算法提高:组合数学| 卡特兰数的实现
|
算法
【过河卒】回溯算法保姆式解题
【过河卒】回溯算法保姆式解题
95 0
三道好题分享
上课睡觉 - AcWing题库
86 0
|
算法 JavaScript 前端开发
日拱算法:解两道“杨辉三角”题
什么是“杨辉三角”,想必大家并不陌生~~ 在「杨辉三角」中,每个数是它左上方和右上方的数的和。
|
机器学习/深度学习 算法
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
|
算法
基础算法练习200题09、水池注水
基础算法练习200题09、水池注水
159 0
基础算法练习200题09、水池注水
|
算法 Python
简单算法
python 简单算法
66 0
下一篇
无影云桌面