过了好几天,今天继续上一篇:数组中的趣味题(一)。文章的内容主要来自本人看过的书籍和其他相关博文,文章内容已经对网上查到的相关资料进行了部分修改,全当作为自己的复习资料吧。当然了,文中难免出现错误,希望大家能帮忙指出来,本人一直希望网友能一起探讨问题,一起指出文中的问题,改正过来,这样看到文章的人才能收获正确的知识,实际上帮助别人的过程也正是自己提高的过程。最近碰到几个这样的人,发这样的评论:“这文章真不怎么地”,“文章中有各种问题啊,这怎么能行”,“哎,楼主还需要提高啊”。说实话,不是楼主度量低,您就指出问题在哪不就好了嘛,大家看到都会感激你,为什么总是说这种模凌两可的话,让人不知道从哪里下手,如果您不想帮忙改正错误,那就不知道您的真正用意是什么了?不要发这种话,没什么意义。您要是不喜欢别人的文章也可以自己写。。。千万别这样发评论,做个高素质的人!!!
1.找出数组中唯一的重复元素
问题描述:给定包含101个元素的数组arr,数组中元素一定属于[1,100],并且[1,100]之间的每个数都在arr中出现过。
解决方案:分析,数组中有101个元素,如果[1,100]之间的每个数出现一次,那就是100个元素了,剩下的那个元素就是唯一的重复出现的元素。我们可以通过遍历arr,得到arr中所有元素的总和,然后既然[1,100]之间的每个数出现一次,那么我们减去1+2+……+99+100的和,结果就是我们需要的唯一的重复出现的元素了。时间复杂度是O(n)。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
2.找出数组中出现奇数次的元素
问题描述:现在有一个整数数组arr,其中的元素只有一个元素出现奇数次,请找出这个元素。
解决方案:对于任意一个数k,有k^k = 0,k^0 = k,所以将arr中所有元素进行异或,那么出现次数为偶数的元素异或后都变成了0,出现次数为奇数的元素异或后得到元素本身。下面写代码就很容易了~~时间复杂度是O(n)。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
3.找出两个数组中满足给定和的数对
问题描述:有两个数组arr1和arr2,两个数组均已经排好序,现在要找出这样的x和y使得x+y=sum,其中sum已知,x是arr1中某个元素,y是arr2中的某个元素。
解决方案:既然数组arr1和arr2中的元素已经排好序了,那么问题就简单了不少。假设arr1[i] + arr2[j] > sum,若arr1下标不变,那么要找到满足条件的x和y,只能取arr2中下标< j 的元素和arr1[i]相加,结果才可能等于sum;假设arr1[i] + arr2[j] < sum,若arr2的下标不变,那么要找到满足条件的x和y,只能取arr1中下标 > i 的元素和arr2[j]相加,结果才可能等于sum。因此我们可以设置两个指针 i 和 j ,分别指向arr1的开始位置和结束位置,这时 i 只能不断变大,j 只能不断变小,直到超过了数组的范围。通过代码更好理解,看代码吧~~时间复杂度是O(n+m),n和m分别是arr1和arr2的大小。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
4.最大子段和
问题描述:对于整数数组arr,求出最大连续子段之和,字段和是这样的: i 和 j 是数组下标并且i <= j ,那么sub_sum = arr[i] + arr[i+1]……+arr[j],就是一段子段和,我们的目的是找到最大的子段和。如果和为负数,按0计算。
解决方案:这个算法,可是算得上是比较经典的算法了,对照着代码,理解一下思路吧:MAX是记录在搜索过程中出现的最大值,也就是最终的最大值保存的地方,而对于tmp的话,tmp > 0,就说明如果tmp继续和后面的数(假设是arr[i])相加,就能继续使得以a[i]结尾的子段和变大,而当tmp < 0 ,就说明这个值不能加到a[i]上,这一定会导致总和不是最大的,tmp的意图比较像是获得“最大前缀和”!!我就说这么多吧,这个东西还是看代码理解吧!!时间复杂度是O(n)。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
5.最大子段积
问题描述:对于整数数组arr,求出最大连续子段积。具体什么是最大连续子段积,我想参考最大字段和应该能知道。
解决方案:和最大子段和的思想和很相似,看代码!时间复杂度是O(n)
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
6.一种特殊的排序(重排问题)
问题描述: 对于整数数组arr中包含0和非0元素,现在要对数组进行处理,使得处理后的结果满足:(1)0都排在数组的前面(2)非0元素都在数组的后面,并且相对顺序不能变化。例如arr[] = {3,0,1,0},经处理后的结果应为:{0,0,3,1}。
解决方案:要完成这个要求,只需要从后向前遍历数组arr,遇到一个非0的数就将其放到数组的后面,遇到的第一个非0元素放在数组的第n-1位置,遇到的第二个非0元素放在数组的第n-2位置(其中n是数组的大小)。这样就完成了题目的要求!!!时间复杂度是O(n)
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
7.找出绝对值最小的数
问题描述:整数数组arr已经排好序,其中包含正数,0负数,数组大小是n,要求找到绝对值最小的数。
解决方案:通过分析有几种情况:(1)若arr[0]和arr[n-1]同号且arr[0]>=0,则绝对值最小的数是arr[0];(2)若arr[0]和arr[n-1]同号且arr[0]<=0,则绝对值最小的数是arr[n-1];(3)若arr[0]和arr[n-1]不同号,则绝对值最小数应该是“最小的正整数”和“最大的负整数”中的一个。关键就是找到这“最小的正整数”和“最大的负整数”。既然数组是已经排好序了,那么可以利用二分。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
文章参考资料:
【1】博文http://www.cnblogs.com/graphics/archive/2010/08/24/1761620.html#link13
【2】《编程之美》