更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~
T:
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
如果用暴力搜索,那就太没意思了,所有的问题都可以用枚举法解决。
我的解法:
把当前array数组的第0号元素,即array[0],与后面的作比较,如果相等,计数器count ++;否则,就把不同的元素放在一个新数组tempArray中,等这一轮遍历完之后:
- 比较count 与 array.length/2的大小,如果前者大于后者,直接返回array[0]元素;
- 即使前者不大于后者,说明这个array[0]不是要寻找的目标元素,此时,记下共有多少与array[0]不同的元素存在(这些元素都在新数组tempArray中),标记为newLength,把tempArray中的元素覆盖在array数组上,继续以上操作;
- 继续以上操作的情况分为两种,一种是array数组中根本就不存在目标元素,此时,有newLength = 0;如果存在,就会从while循环的判断条件跳出。
code:
/**
* T: 数组中出现次数超过一半的数字
*
* 题目描述
* 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
* 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,
* 超过数组长度的一半,因此输出2。如果不存在则输出0。
*
* date: 2015.11.27
* @author SSS
*
*/
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if (array.length == 0 || array == null) {
return 0;
}
int targetNum = 0;
int newLength = array.length;
int []tempArray = new int[array.length];
// 统计每个数字在数组中的个数
int count = 0;
int curNum = array[0];
while (count <= array.length / 2) {
// 说明数组已到最后
if (newLength == 0) {
break;
}
int k = 0;
count = 0;
//每次都用array数组的第0号元素与后面的相比,把不同的元素放在新数组tempArray中
for (int i = 0; i < newLength; i++) {
if (array[0] != array[i]) {
tempArray[k++] = array[i];
} else {
count ++;
}
}
curNum = array[0];
newLength = k;
for (int i = 0; i < newLength; i++) {
array[i] = tempArray[i];
}
}
// 这种情况下,不是经由while退出的,而是因为找不到此类元素而退出的,要返回0
if (count <= array.length / 2) {
targetNum = 0;
} else {
targetNum = curNum;
}
return targetNum;
}
}
更高效的解法
首先看一个规律:
给定一个数组: a r r a y = [ a ( 1 ) , . . . , a ( j ) , a ( j + 1 ) , . . . , a ( n ) ] array = [a(1), ... , a(j) , a(j+1), ... , a(n)] array=[a(1),...,a(j),a(j+1),...,a(n)]
将数组分为两部分:
[
a
(
1
)
,
.
.
.
,
a
(
j
)
]
[a(1), ... , a(j)]
[a(1),...,a(j)] 和
[
a
(
j
+
1
)
,
.
.
.
,
a
(
n
)
]
[a(j+1), ... , a(n)]
[a(j+1),...,a(n)]
设想:如果在
[
a
(
1
)
,
.
.
.
,
a
(
j
)
]
[a(1), ... , a(j)]
[a(1),...,a(j)] 部分中,如果某个元素正好只占一半,单考虑这部分数组,该元素是不会成为目标元素的,那么可以继续寻找下一部分数组中能超过一半的元素。
而本代码的思想也是如此,设定初始元素,看其在一部分数组中占有的比例,当比例达到一半时,就抛弃,相当于前半部分不曾有过,把下一个元素设定为主对比元素,重复此步骤。
以上讲解也说不清楚,看代码,比较简单:
code:
/**
* T: 数组中出现次数超过一半的数字
*
* 题目描述
* 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
* 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,
* 超过数组长度的一半,因此输出2。如果不存在则输出0。
*
* date: 2015.11.27 18:49
* @author SSS
*
*/
public class Solution {
/**
* 解题的另一种方式,时间复杂度O(n)
* @param array
* @return
*/
public int MoreThanHalfNum_Solution(int [] array) {
int targetNum = 0;
if (array.length == 0 || array == null) {
return 0;
}
//当前num元素的计数
int count = 1;
int num = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] == num) {
count ++;
} else {
count --;
}
// 小于零,则说明array[i]之前的元素中,没有一个元素的个数超过了半数,
// 顶多是一半,或者更少,这个时候就要从后面的元素重新开始找
if (count < 0) {
num = array[i];
count = 1;
}
}
int numCount = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
numCount ++;
}
}
if (numCount <= array.length / 2) {
return 0;
} else {
targetNum = num;
}
return targetNum;
}
}
更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~