题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

思路:
解法一:基于partition函数的O(n)算法。
        先用partition函数对数组进行交换修改,然后对数组里的无效情况进行判断,还有计算通过partition计算出来的数字出现的次数是否超过一半。
解法二:数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1,;如果下一个数字和我们之前保存的数字不同,则次数减1,。如果次数为0,我们需要保存下一个数字,并把次数设为1.由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。
 
测试用例:
1)功能测试(输入的数组中存在一个出现次数超过数组长度一半的数字,输入的数组中不存在一个出现次数超过数组长度一半的数字);
2)特殊输入测试(输入的数组中只有一个数字、输入null指针)。
 
实现代码:
package com.yyq;
/**
* Created by gao on 15-10-23.
*/
public class MoreThanHalfNumber {
public static boolean g_bInputInvalid = false;
public static boolean checkInvalidArray(int[] numbers, int length) {
g_bInputInvalid = false;
if (numbers == null || length <= 0) {
System.out.printf("Numbers is null! Invalid Parameters.");
g_bInputInvalid = true;
}
return g_bInputInvalid;
}
public static boolean checkMoreThanHalf(int[] numbers, int length, int number) {
int times = 0;
for (int i = 0; i < length; i++) {
if (number == numbers[i])
times++;
}
boolean isMoreThanHalf = true;
if (times * 2 <= length) {
System.out.println("the number you find is not more than half.");
isMoreThanHalf = false;
g_bInputInvalid = true;
}
return isMoreThanHalf;
}
public static int Partition(int[] numbers, int length, int start, int end) {
if (numbers == null || length <= 0 || start < 0 || end >= length) {
System.out.printf("Invalid Parameters!");
return -1;
}
int index = numbers[start];
while (start < end) {
while (start < end && numbers[end] >= index) end--;
numbers[start] = numbers[end];
while (start < end && numbers[start] <= index) start++;
numbers[end] = numbers[start];
}
numbers[start] = index;
return start;
}
//==================方法一:partition========================
public static int moreThanHalfNum_solution1(int[] numbers, int length) {
if (checkInvalidArray(numbers, length)) {
return 0;
}
int middle = length >> 1;
int start = 0;
int end = length - 1;
int index = Partition(numbers, length, start, end);
while (index != middle) {
if (index > middle) {
end = index - 1;
index = Partition(numbers, length, start, end);
} else {
start = index + 1;
index = Partition(numbers, length, start, end);
}
}
int result = numbers[middle];
if (!checkMoreThanHalf(numbers, length, result)) {
result = 0;
}
return result;
}
public static int moreThanHalfNum_solution2(int[] numbers, int length) {
if (checkInvalidArray(numbers, length)) {
return 0;
}
int result = numbers[0];
int times = 1;
for(int i = 1; i < length; i++){
if (times == 0){
result = numbers[i];
times = 1;
}
else if(numbers[i] == result){
times ++;
}else{
times--;
}
}
if (!checkMoreThanHalf(numbers, length, result)) {
result = 0;
}
return result;
}
// ====================测试代码====================
public static void Test(String testName, int[] numbers, int length, int expectedValue, boolean expectedFlag)
{
if(testName != null)
System.out.println("\n"+testName+" begins: ");
int[] copy = new int[length];
for(int i = 0; i < length; ++i)
copy[i] = numbers[i];
System.out.printf("Test for solution1: ");
int result = moreThanHalfNum_solution1(numbers, length);
if(result == expectedValue && g_bInputInvalid == expectedFlag)
System.out.println("Passed.");
else
System.out.println("Failed.");
System.out.printf("Test for solution2: ");
result = moreThanHalfNum_solution2(copy, length);
if(result == expectedValue && g_bInputInvalid == expectedFlag)
System.out.println("Passed.");
else
System.out.println("Failed.");
copy = null;
}
// 存在出现次数超过数组长度一半的数字
public static void Test1()
{
int numbers[] = {1, 2, 3, 2, 2, 2, 5, 4, 2};
Test("Test1", numbers, numbers.length, 2, false);
}
// 不存在出现次数超过数组长度一半的数字
public static void Test2()
{
int numbers[] = {1, 2, 3, 2, 4, 2, 5, 2, 3};
Test("Test2", numbers, numbers.length, 0, true);
}
// 出现次数超过数组长度一半的数字都出现在数组的前半部分
public static void Test3()
{
int numbers[] = {2, 2, 2, 2, 2, 1, 3, 4, 5};
Test("Test3", numbers, numbers.length, 2, false);
}
// 出现次数超过数组长度一半的数字都出现在数组的后半部分
public static void Test4()
{
int numbers[] = {1, 3, 4, 5, 2, 2, 2, 2, 2};
Test("Test4", numbers, numbers.length, 2, false);
}
// 数组为1个元素
public static void Test5()
{
int numbers[] = {1};
Test("Test5", numbers, 1, 1, false);
}
// 输入空指针
public static void Test6()
{
Test("Test6", null, 0, 0, true);
}
public static void main(String[] args)
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
}
}
 
输出结果:
 
Test1 begins:
Test for solution1: Passed.
Test for solution2: Passed.
 
Test2 begins:
Test for solution1: the number you find is not more than half.
Passed.
Test for solution2: the number you find is not more than half.
Passed.
 
Test3 begins:
Test for solution1: Passed.
Test for solution2: Passed.
 
Test4 begins:
Test for solution1: Passed.
Test for solution2: Passed.
 
Test5 begins:
Test for solution1: Passed.
Test for solution2: Passed.
 
Test6 begins:
Test for solution1: Numbers is null! Invalid Parameters.Passed.
Test for solution2: Numbers is null! Invalid Parameters.Passed.
 
Process finished with exit code 0

 

P163、面试题29:数组中出现次数超过一半的数字的更多相关文章

  1. 剑指Offer:面试题29——数组中出现次数超过一半的数字(java实现)

    PS:在前几天的面试中,被问到了这个题.然而当时只能用最低效的方法来解. 问题描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2, ...

  2. 《剑指offer》面试题39. 数组中出现次数超过一半的数字

    问题描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, ...

  3. 面试题五 数组中出现次数超过一半的数字 时间为O(n)

    也就是说 该数字出现的次数比其他所有数字出现次数的和还要多. 因此可以保存两个值,一个数字,一个次数. 遍历时 1.如果数字相同,count++ 2.如果count == 0 count = 1 nu ...

  4. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

  5. 九度OJ 1370 数组中出现次数超过一半的数字

    题目地址:http://ac.jobdu.com/problem.php?pid=1370 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2 ...

  6. 《剑指offer》第三十九题(数组中出现次数超过一半的数字)

    // 面试题39:数组中出现次数超过一半的数字 // 题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例 // 如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, ...

  7. 数组中出现次数超过一半的数字 -java

    数组中出现次数超过一半的数字 -java 方法一: 数组排序,然后中间值肯定是要查找的值. 排序最小的时间复杂度(快速排序)O(NlogN),加上遍历. 方法二: 使用散列表的方式,也就是统计每个数组 ...

  8. 【C语言】统计数组中出现次数超过一半的数字

    //统计数组中出现次数超过一半的数字 #include <stdio.h> int Find(int *arr, int len) { int num = 0; //当前数字 int ti ...

  9. 《剑指offer》— JavaScript(28)数组中出现次数超过一半的数字

    数组中出现次数超过一半的数字 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超 ...

  10. 剑指Offer - 九度1370 - 数组中出现次数超过一半的数字

    剑指Offer - 九度1370 - 数组中出现次数超过一半的数字2013-11-23 03:55 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组 ...

随机推荐

  1. 如何在IOS开发中在自己的framework中添加.bunble文件

    今天就跟大家介绍一下有关,如何在IOS开发中在自己的framework中添加.bunble文件,该文章我已经在IOS教程网(http://ios.662p.com)发布过来,个人觉得还是对大家有帮助的 ...

  2. poj 1659 Frogs' Neighborhood Havel-Hakimi定理 可简单图定理

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4098136.html 给定一个非负整数序列$D=\{d_1,d_2,...d_n\}$,若存 ...

  3. 译文:Javascript-function's return

    个人理解+google翻译.如有错误,请指正.原文来自MDN:return 概要 由function返回指定值. 版本信息 实现: JavaScript 1.0, NES 2.0(NES:游戏机在欧洲 ...

  4. 关于Socket编写简单聊天工具的总结(原创)

    这段时间再看socket编程,虽然现在是刚刚接触,但是还是忍不住想写一篇总结,来激励自己努力学习,写的不好的地方,还请大家指教啊! 下面针对一个简单的发送消息和文件的程序说说吧.   首先是服务器需要 ...

  5. Qt Creator (C++)保存文件

    最近在学习QT Creator,感觉很是头大.可能是刚刚学的原因吧,感觉完全没有C#好,好多东西完全搞不懂. C++虽然很灵活,但是也可能是太灵活了,总是搞得人一头雾水. 一个简简单单的保存文件,就让 ...

  6. MYSQL数据库主主同步实战

    MYSQL支持单向.异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.主服务器将更新写入二进制日志文件,并维护日志文件的一个索引以跟踪日志循环.当一个从服务器连接到主服务 ...

  7. xml学习总结(一)

    xml DTD 定义元素<!ELEMENT 元素名 元素类型描述 > (1)元素类型描述:任意类型,字符串型,空元素,包含子元素,混合类型 任意类型: <?xml version=& ...

  8. CentOS7安装nagios并配置出图详解

    目录 开始之前 系统环境 监控内容 所需软件包 台机器,全都按照CentOS7最小化模式安装系统 系统版本号 [root@localhost ~]# cat  /etc/redhat-release ...

  9. 【原创】一起学C++ 之指针、数组、指针算术 ---------C++ primer plus(第6版)

    C++ Primer Plus 第6版 指针和数组基本等价的原因在于指针算术! 一.指针 ⑴整数变量+1后,其值将增加1: ⑵指针变量+1后,增加的量等于它指向的类型的字节数: ⑶C++将数组名解析为 ...

  10. 【git】学习路径失败了

    期初规划:搭建git远程服务器  使用gitlab作为管理工具 过程遇到的问题 1.gitlab不能安装到win ,且对centos要求6以上,我只有一台centos5  让运维帮升级 ...等待.. ...