数组中的趣味题一

无论是参加面试还是笔试,数组都是常考的内容,并且考察数组的知识往往结合着比较有意思的算法。在这里参照网上的资料和平时看过的相关书籍总结一下,作为自己的面试复习材料吧。我知道这个总结肯定有遗漏或者是不对的地方,希望大家看到可以优化和改正的的地方,帮帮忙给点新思路吧。谢谢大家~~

1.求数组中的最大值(最小值)



问题描述:给定一个整数数组arr,找出其中的最大值(最小值)。

解决思路:传统的方法就是遍历一次数组即可得到最大值(最小值),时间复杂度是O(N);现在说另外一个思路利用二分,即将数组分成元素数目接近相等的两部分,然后分别找到两个部分的的最大值(最小值),最后合并,比较两个部分的最大值(最小值),即可得到最终的最大值(最小值)。

代码:

1 int FindMax(int *arr,int l,int r)
 2 {
 3     if(l == r)
 4     {
 5         return arr[l];
 6     }
 7     int mid = (l+r)/2;
 8     int LMAX,RMAX;
 9     LMAX = FindMax(arr,l,mid);
10     RMAX = FindMax(arr,mid+1,r);
11     return max(LMAX,RMAX);
12 }

2.求数组中出现次数超过一半的元素



问题描述:整数数组arr中,一定存在一个数x,x在数组arr中出现的次数过半,请找出这个数x。

解决思路:既然x在数组中出现的个数过半,那么若将数组arr排序,显然数组中arr[N/2]一定是要找的x(N数组arr中元素的个数)。这个思路的时间复杂度取决于排序算法的时间复杂度,因此整个算法的时间复杂度达到O(N*logN)是没有问题的。既然x在数组arr中出现的次数过半,那么在遍历数组的过程中若每次遇到与x不同的数,x出现的数目-1,出现x,则x出现的数目+1,那么到最后剩下的一定是x。这种情况下,只需要遍历一次数组,时间复杂度是O(N),但是,难点是我们事先不知道x是什么,那么算法怎么实现呢?看看代码就明白啦~~

代码:

 1 int Find(int *arr,int n)
 2 {
 3     int tmp = arr[0];
 4     int count = 1;//计数器
 5     for(int i = 1 ; i < n ; i++)
 6     {
 7         if(count == 0)
 8         {
 9             tmp = arr[i];
10             count = 1;
11         }
12         else if(tmp == arr[i])
13         {
14             count++;
15         }
16         else
17         {
18             count--;
19         }
20     }
21     return tmp;
22 }

3.求数组中元素间的最近距离(一)



问题描述:数组arr[]中存在N个元素(数组中N个元素没有范围),找到这样的a和b,使得abs(a,b)的值最小。

解决思路:这是个比较简单的问题了,思路也很容易想到,只需要将arr进行排序,这时数组中元素的最短距离只可能是相邻的两个元素之间,这个算法的时间复杂度是:O(N*logN)。如果不对数组进行排序,那么就需要枚举数组中的每两个元素了,求出最小距离,时间复杂度是O(N*N)。

代码:

 1 int Find(int *arr,int n)
 2 {
 3     int tmp = arr[0];
 4     int count = 1;//计数器
 5     for(int i = 1 ; i < n ; i++)
 6     {
 7         if(count == 0)
 8         {
 9             tmp = arr[i];
10             count = 1;
11         }
12         else if(tmp == arr[i])
13         {
14             count++;
15         }
16         else
17         {
18             count--;
19         }
20     }
21     return tmp;
22 }

4.求数组中元素间的最近距离(二)



问题描述:和上一个问题相似,区别是arr中的数组元素的取值范围的。

解决思路:既然加了一个条件,那么看来就是利用这个条件进行优化了。既然数组中的元素有了范围,不妨先假设数组中值在0~100之间,那么我们可以这样做,申请一个数组bool fuzhu[100],这样遍历一遍数组,记录arr中出现的元素,假设arr中包含4,那么arr[4]=1,然后在遍历一遍fuzhu,fuzhu[i]值为1,表示i存在于arr中,这样计算“相邻”的fuzhu[]=1的元素,计算出最小距离。用一个大家看书时比较不愿意看到的词:经分析,时间复杂度是O(N+M),其中M是aar中元素的所在区间大小。

代码:

1 int MinDistance(int *arr,int n)
 2 {
 3     bool fuzhu[101];
 4     int first,second;
 5     int tmp_MIN = INF;
 6     memset(fuzhu,false,sizeof(fuzhu));
 7     //遍历找出在arr出现的数
 8     for(int i = 0 ; i < n ; i++)
 9     {
10         fuzhu[arr[i]] = true;
11     }
12     int j = 0;
13     while(j < 101 && !fuzhu[j])
14     {
15         j++;
16     }
17     first = j++;//获取fuzhu中第一个不为0的数
18     while(j < 101 && !fuzhu[j])
19     {
20         j++;
21     }
22     second = j++;//获取fuzhu中第二个不为0的数
23     while(1)
24     {
25         if(second - first < tmp_MIN)
26         {
27             tmp_MIN = second - first;
28         }
29         while(j < 101 && !fuzhu[j])
30         {
31             j++;
32         }
33         if(j > 100) break;
34         first = second;
35         second = j++;
36     }
37     return tmp_MIN;
38 }

小结:大家看后,肯定会说arr中数组范围也可能是负数啊,那怎么办呢?注意了,这个题要求的是,最近距离。下标虽然不能为负,但是只要移位存储就完事了吗!毕竟只需要最小距离啊,平行移动不影响最小距离。比如arr中元素的范围是-100~~100,那么只需要当出现-100,对应的fuzhu[-100+100] = fuzhu[0] = true。不就可以了吗?

5.求两个数组中的相同元素



问题描述:现在有两个已经排好序的整数数组arr1和arr2,找出两个数组中的相同元素。

解决思路:既然已经排好序了,那么问题就简单了,假设arr1[2]和arr2[4]相等,那么搜索arr1[3]只需要和arr2中下标4及以后的元素比较。如果arr1和arr2中元素的个数分别是N和M,那么这个算法的时间复杂度是O(N+M),不妨先看看代码。

代码:

 1 // 找出两个数组的相同元素
 2 void FindSame(int *arr1, int *arr2,int n,int m)
 3 {
 4     int i = 0;
 5     int j = 0 ;
 6     while (i < n && j < m)
 7     {
 8         if (arr1[i] < arr2[j])
 9             ++i;
10         else if(arr1[i] == arr2[j])
11         {
12             cout<<arr1[i]<<endl;
13             ++i;
14             ++j;
15         }
16         else//arr1[i] > arr2[j]
17             ++j ;
18     }
19 }

小结:对于这个问题arr1和arr2数组都已经是排好序的,那么如果两个数组都不是排好序的呢??后来在网上查了点资料,发现这样一个哈希的思路:遍历一遍arr1,建立哈希表,然后遍历一遍arr2,看看哪一个元素存在于哈希表中。这样一来时间复杂度还是O(N+M),但是多引入了O(N)的空间复杂度。

时间: 2024-12-28 23:14:46

数组中的趣味题一的相关文章

【趣味算法题】在数组中,对于所有元素,找出比当前元素大的下一个元素

在数组中,对于所有元素,找出比当前元素大的下一个元素 意思就是,eg.  数组为 3 1 2 5 4 6 7 那么我们需要得到的结果应该是  5 2 5 6 6 7 -1 解决方法如下: 暴力匹配: O (n ^ 2 ) 的效率对所有元素匹配过去,效率非常的低 经过提示, 我想到的一种 O ( nlg n ) 效率的算法 只需要对数组扫描一次,我们用一个 Priority_queue 来得到当前最小的元素 Prority_queue 存放的数据结构为: struct sc { int key,

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

编程题:指针输出数组的灵活性。功能:输出数组中全部元素

#include<stdio.h> void main() { int *p,i; int a[5]={1,2,3,4,5}; p=a; printf("\n"); for(;p<a+5;p++) printf("%d\t",*p); } 编程题:指针输出数组的灵活性.功能:输出数组中全部元素,布布扣,bubuko.com

编程题:展示指针与数组的输出方式,功能:输出数组中的全部元素

#include<stdio.h> void main() { int *p,i; int a[5]={1,2,3,4,5}; p=a; for(i=0;i<5;i++) printf("%d\t",a[i]); printf("\n"); for(i=0;i<5;i++) printf("%d\t",*(p+i)); } 编程题:展示指针与数组的输出方式,功能:输出数组中的全部元素,布布扣,bubuko.com

js中字符和数组一些基本算法题

最近在刷 fcc的题,跟升级打怪一样,一关一关的过,还挺吸引我的.今天抽时间把 Basic Algorithm Scritping  这部分题做了,根据一些提示,还是比较简单的.有些题的处理方式 方法,我想值得借鉴.比如在项目中有时候要处理一个字符,如果想不到一些相关的方法,还挺费事的,所以,在此记录下来,如果以后遇到一些字符或者数组处理,可以来翻翻这篇文章,希望以此得到一些提示而不是去翻文档.   看到此博文的博友,有更好更简单的代码或者好的想法,请留言交流(我一直觉得只有学习别人的优秀代码才

第11题:移除数组中的重复元素

/* 前几天去爬泰山了,一直没更新,上山时还没什么感觉,下山后简直要崩溃啊,骨头都散了,继续更新...... */ 第11题:移除数组中的重复元素 给定一个升序排列的数组,去掉重复的数,并返回新的数组的长度. 例如: 数组A = {1, 1, 2},你的函数应该返回长度2,新数组为{1, 2} 要求: 不能新开数组分配额外的空间.即常数空间限制. 提示: 输入一个整数n,以及其对应的数组A[n],输出新数组长度 样例输入 5 0 0 1 1 2 样例输出 3 解析: #include <stdi

找出数组中两个只出现一次的数字 【微软面试100题 第六十一题】

题目要求: 一个整型数组里除了两个数字机之外,其他的数字都出现了两次. 请写程序找出这两个只出现一次的数字.要求时间复杂度O(N).空间复杂度O(1). 参考资料:剑指offer第40题. 题目分析: 已知: 1.两个相同的数字异或的结果为0,即a^a = 0. 2.两个不相同的数字异或的结果的二进制中某一位为1,则这两个数字的二进制中对应位一个为0,一个为1.如3^2 = 1,对于最低位的二进制,3的最低位二进制为1,2的最低位二进制位0,则结果1的最低位二进制肯定为1. 假设原数组中只出现一

趣味题,文本中洞的数量

厨师写了一些文字在一张纸上,现在他想知道有多少洞在文本中.什么是一个洞?如果您认为纸为平面和一个字母为平面上的曲线,那么每个字母划分平面成区域.例如字母“A”,“D”,“O”,“P”,“R”分裂平面分成两个区域,所以我们说每个字母有一个孔.同样的,字母“B”有两个孔和字母如“C”,“E”,“F”,“K”有没有漏洞.我们说,在文本中的孔的数量等于文本中的字母的孔的总数.帮助厨师,以确定有多少孔在文本中. 输入 第一行包含一个整数T <= 40,测试用例的数量.测试案例可循.每个测试案例的唯一行只包

第14题:查找升序数组中的两数,使其和为输入数字

欢迎转载,转载请注明出处:http://blog.csdn.net/alading2009/article/details/45080773 第14题:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求: 时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可.例如输入数组1.2.4.7.11.15和数字15.由于4+11=15,因此输出4和11. 两头向中间靠拢,因为是升序数组,两数之和大了就尾指针前移,两数之和小了就头指针后