查找数组中出现次数超过一半的数字(出现最多的一堆数)
描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
分析
如果对数组顺序排序,一切都简单,但是会消耗至少N*logN的时间复杂度。使用Map集合的特性,用数组存储的值作为Key,出现次数作为Value,这样时间复杂度可以减低到O(N),同时由于只需要找出最多的一个数字所以只要这个数字出现次数大于length/2那么他必定是出现最多的,时间复杂度可以进一步降低到O(N/2)到O(N)之间。同理一般很多字符查找找出其中最大的几个字符都可以使用这种方式-利用Map集合的特性
代码
public int MoreThanHalfNum_Solution(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < array.length; i++) {
Integer count = map.get(array[i]);
if (count == null) {
count = 1;
} else {
count += 1;
}
map.put(array[i], count);
if (count > array.length / 2) {
return array[i];
}
}
return 0;
}
测试
public void testMoreThanHalfNum_Solution() {
int[] array = { 1, 2, 3, 2, 2, 2, 5, 4, 2 };
assertEquals(2, solution.MoreThanHalfNum_Solution(array));
}
规律二维数组中的查找
题目描述
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 如果含有就输出其在数组 中存在的位置,格式如:“横坐标,纵坐标”,如果不包含就返回空String
分析
思路:首先我们选择从左下角开始搜寻,(为什么不从左上角开始搜寻,左上角向右和向下都是递增,那么对于一个点,对于向右和向下会产生一个岔路;如果我们选择从左下脚开始搜寻的话,如果大于就向右,如果小于就向下)。同理:从右上角搜索效果一样。
通过从下往上排除大于target的数组集合和从左往右排除小于target的数组集合寻求交集
代码
public static String Find(int[][] array, int target) {
int size = array.length - 1;
int i = 0;
while (i < array[0].length && size >= 0) {
if (array[size][i] > target) {
size--;
} else if (array[size][i] < target) {
i++;
} else {
return size + "," + i;
}
}
return "";
}
测试
int[][] array = { { 1, 2, 8, 9 }, { 2, 4, 9, 12 }, { 4, 7, 10, 13 },
{ 6, 8, 11, 15 } };
public void testFind() {
assertEquals("", ArraySolution.Find(array, 5));
assertEquals("0,0", ArraySolution.Find(array, 1));
assertEquals("2,3", ArraySolution.Find(array, 13));
}
数组中只出现一次的数字
描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
num1,num2分别为长度为1的数组。传出参数 将num1[0],num2[0]设置为返回结果
代码
public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < array.length; i++) {
if (list.contains(array[i])) {
list.remove(new Integer(array[i]));
} else {
list.add(array[i]);
}
}
if (list.size() == 2) {
num1[0] = list.get(0);
num2[0] = list.get(0);
} else {
num1[0] = 0;
num2[0] = 0;
}
}
数组中的逆序对
描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
分析
递归
代码
public int InversePairs(int[] array) {
if (array == null | array.length == 0 || array.length == 1) {
return 0;
}
getPairs(array, 0);
return count;
}
public int count = 0;
public void getPairs(int[] array, int n) {
if (n > array.length - 2) {
return;
}
for (int i = n; i < array.length - 1; i++) {
if (array[n] > array[i + 1]) {
count++;
}
}
getPairs(array, n + 1);
}
测试
public void testInversePairs() {
int[] array = { 1, 2, 3, 4, 7, 6, 5 };
int[] array2 = { 6, 5, 4, 3, 2, 1 };
assertEquals(3, solution.InversePairs(array));
assertEquals(15, solution.InversePairs(array2));
}