算法-统计字符出现次数

1,029 阅读3分钟

审题

一个整数数组,只有一个数据是出现一次,其他都出现两次。找到出现一次的数据。


示例
[1,2,2,3,3] //1出现一次

[22133] //1出现一次

思想

其实还是比较数据,只要是比较数据,那么就是冒泡循环,即外一层里一层。

唯一的区别就是,这个题目需要计算次数,而不是排序题目需要排序。

核心步骤

1.比较数据 //基于冒泡排序的外循环和内循环

if(相等) //相等,说明是两次  
  break; //结束内循环

2.用什么数据结构存储次数//map还是数组?map,数组不行,因为数组不能判断包含关系即某个key是否存在。

map<2,2> //2这个数据的次数是2。

在内循环之前要判断外循环的数据是否在map里,如果在就不用比较了,直接结束内循环;如果不在,再内循环比较。

步骤

1.每一趟内循环比较
2.计算次数,只要出现一次相等,那么结束当前内循环
3.如果内循环之前,map包含,那么也结束当前内循环

伪代码

for(){
  if(map是否包含){
      //是,就结束内循环
  }

 for(){
   if(相等) //相等,说明是两次
   break; //结束内循环(内循环包含多次) //continue只结束当前这一次循环。
 }
}

完整源码

基于冒泡算法实现

思想
1.冒泡
外循环
内循环 //总共两层循环

2.比较数据
数据相等,说明出现两次;
不等,说明出现一次。

import java.util.HashMap;

public class CountNum {

	public static void main(String[] args) {
		//输入数据
		int[] a= {2,2,1,3,3};
		
		//查找只出现一次的数据
		int i = countNum(a); 
		
		//输出数据
		if(i==-1) { //没找到数据
			System.out.print("没找到");
		}else { //找打数据
			System.out.print(a[i]);
		}
	}
	
	//找到只出现一次的数据
	private static int countNum(int[] a) {
//		HashMap<Integer, Integer> map = new HashMap<>();
		
		for (int i = 0; i < a.length; i++) {
//			if(map.containsKey(i)) { //查询数据 //什么时候写数据到map?如果只有一个数据出现一次,那么不需要存储数据和次数,也就不需要使用map;如果有多个数据出现一次,那么就需要存储数据,可以使用map。
//				return i;
//			}
			
			for (int j = 0; j < a.length; j++) {
				//i不和自己比较
				if(i==j) { //如果相等,就跳过本次循环
					continue;
				}
				
				//i和自己索引不一样的所有数据比较
				if(a[i] == a[j]) { //如果有相等的数据,那么说明该数据出现两次,然后跳过内循环
					break;
				}
				
				if(j==(a.length-1)) { //最后一个数据仍然不相等,说明当前数据只出现一次
					return i;
				}
			}
		}
		return -1; //没找到
	}

}

//总结 速度 其实就是冒泡排序,所以是N*N。怎么才能提高速度?

基于异或运算实现

思想
1.异或运算
相同的数据异或运算的结果是0;
不同的数据是1。

2.异或数组里的所有数据
比如有5个数据,异或这5个数据,最后结果就是那个只出现一次的数据,因为其他数据都出现两次,所以彼此异或运算的时候互相抵消了。

package CountNum;

public class CountNum2 {

	public static void main(String[] args) {
		//输入数据
		int[] a= {2,2,1,3,3};
		
		//查找只出现一次的数据
		int result = countNum(a); 
		
		//输出数据
		System.out.println(result);
	}
	
	//找到只出现一次的数据
	private static int countNum(int[] a) {
		int result = a[0];
		for (int i = 1; i < a.length; i++) {
			result ^= a[i]; //异或运算
		}
		return result; //最后结果就是那个只出现一次的数据,因为其他数据都出现两次,所以彼此异或运算的时候互相抵消了
	}

}

//总结 速度 N

举一反三-有两个数据出现一次

待补充


参考
剑指offer