题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为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. Layout.xml中控件的ID命名方式

    控件 缩写 LayoutView lv RelativeView rv TextView tv Button btn ImageButton imgBtn ImageView mgView 或则 iv ...

  2. SSH连接时出现Host key verification failed的原因及解决方法

    SSH连接的时候Host key verification failed. [root@cache001 swftools-0.9.0]# ssh 192.168.1.90@@@@@@@@@@@@@@ ...

  3. javascript显示倒计时控制按钮

    html: <a><span id="sendAgain" onclick="sendEmail()">2.再次发送激活邮件</s ...

  4. 【解惑】深入jar包:从jar包中读取资源文件

    [解惑]深入jar包:从jar包中读取资源文件 http://hxraid.iteye.com/blog/483115 TransferData组件的spring配置文件路径:/D:/develop/ ...

  5. gulp 不是内部或者外部命令 或者 webpack 不是内部或者外部命令

    gulp安装也正常,但是就是查看gulp -v的时候报错,原因:缺少系统变量PATH或者PATH变量错误 提示:这个系统变量PATH,直接追加就好(多个变量值用分号;隔开),不要删除已经有的系统变量P ...

  6. HTTP Header 详解【转】

    原文出自:http://kb.cnblogs.com/page/92320/ HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议.HTTP协议采用 ...

  7. PHP将二进制文件存入数据库以及从数据库中读取二进制文件

    <?php $file = 'abcd.sqlite'; mysql_connect('localhost','root','123456'); mysql_select_db('zblog') ...

  8. WordPress 模板常用函数

    WordPress 基本模板文件 一套完整的 WordPress 模板应至少具有如下文件: style.css : CSS(样式表)文件 index.php : 主页模板 archive.php : ...

  9. 正则表达式模块re

    正则表达式通过特定的式子匹配某种类型的字符串.对字符串进行匹配验证或者从大量的字符串里提取出特定的信息. 正则表达式包含普通字符和特殊字符.大部分的普通字符如‘A’或‘0’可以简单的来匹配自己.如te ...

  10. ios实现截屏(转)

    -(UIImage*) makeImage {  UIGraphicsBeginImageContext(self.view.bounds.size);  [self.view.layer rende ...