package class02; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; /** * Code03的变型 * 有一个数组arr,其中只有一种数"没有"出现K次,其余所有的数都都出现了M次。 * 求出这个没有出现K次的数字。 * K < M,M > 1。 */ public class Code03_KM_V02 { public static int test(int[] arr, int k, int m) { Map<Integer, Integer> map = new HashMap<>(); for (int num : arr) { if (map.containsKey(num)) { map.put(num, map.get(num) + 1); } else { map.put(num, 1); } } int ans = 0; for (int num : map.keySet()) { if (map.get(num) == k) { // ans = num; // break; return num; } } return -1; } public static int[] randomArray(int maxKinds, int range, int k, int m) { int kTimesNum = randomNum(range);//随机出一个数,作为真命天子。也就是出现了k次的那个数。 //真命天子出现的次数,times。 //0.5的概率是k次,其余的概率出现任意次。只要小于m就行。 int times = Math.random() < 0.5 ? k : ((int) (Math.random() * (m - 1)) + 1); int numKinds = (int) (Math.random() * maxKinds) + 2;//数组中至少有两种数 //数组长度为:k * 1 + (numKinds - 1) * m /*int[] arr = new int[k + (numKinds - 1) * m];*/ int[] arr = new int[times + (numKinds - 1) * m]; int index = 0; /*for (; index < k; index++) {*/ for (; index < times; index++) { arr[index] = kTimesNum;//k个出现了k次的kTimeNum } numKinds--;//kTimeNum这种数已经填完了,所以数字的种数要减一。 HashSet<Integer> set = new HashSet<>(); set.add(kTimesNum);//在set中添加第一个数,kTimesNum。 while (numKinds != 0) {//只要数字的种类numKinds没有减到0,就一直随机生成一个数字。并将numKinds--。 int curNum; do { curNum = randomNum(range); } while (set.contains(curNum));//如果随机出的数,之前已经出现过了。重新去随机生成一个数。 set.add(curNum); numKinds--; // for (; index < arr.length; index++) { // arr[index] = curNum; // } //一次完整的for循环走完,填m个curNum;一次完整的for循环走完,填m个curNum;知道while循环结束。 for (int i = 0; i < m; i++) { arr[index++] = curNum;//index一直在++。走一次完整的for循环,index就加 m次。 } } //arr填充完毕。 //先不着急返回arr,此时的arr太整齐了。打乱顺序再返回。 //让i位置的数,随机找一个数,交换。 for (int i = 0; i < arr.length; i++) { int j = (int) (Math.random() * arr.length);//j在[0, arr.length - 1]上,不会越界。 int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } return arr; } //[-range, +range]。have a look。[-(range-1), +(range-1)] public static int randomNum(int range) { int num = ((int) (Math.random() * range) + 1) - ((int) (Math.random() * range) + 1); return num; } public static void main(String[] args) { int kinds = 30; int range = 100; int testTimes = 1000; int max = 9; System.out.println("测试开始!"); for (int i = 0; i < testTimes; i++) { int num1 = (int) (Math.random() * max) + 1;//num1属于[1, 9] int num2 = (int) (Math.random() * max) + 1;//num2属于[1, 9] int k = Math.min(num1, num2); int m = Math.max(num1, num2); if (k == m) {//必须 k<m m++; } int[] arr = randomArray(kinds, range, k, m); int ans1 = test(arr, k, m); int ans2 = onlyKTimes(arr, k, m); if (ans1 != ans2) { System.out.println(ans1); System.out.println(ans2); System.out.println("k = " + k); System.out.println("m = " + m); System.out.println("arr = " + Arrays.toString(arr)); System.out.println("oops!"); break; } } System.out.println("测试结束!"); } public static int onlyKTimes(int[] arr, int k, int m) { //先定义一个长度位为32的整数数组,叫t。 //每一位用来标记arr中的所有num,在i位置的1出现了几个。 int[] t = new int[32]; for (int num : arr) { for (int i = 0; i < 32; i++) { t[i] += (num >> i) & 1; } } int ans = 0; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for (int i = 0; i < 32; i++) { if (t[i] % m == 0) { continue; } if (t[i] % m == k) { ans |= 1 << i; } else { return -1; } } if (ans == 0) { int count = 0; for (int i = 0; i < arr.length; i++) { if (arr[i] == 0) { count++; } } if (count != k) { System.out.println("count = " + count); System.out.println("k = " + k); System.out.println("m = " + m); System.out.println("arr = " + Arrays.toString(arr)); return -1; } } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> return ans; } // public static void main(String[] args) { // int[] arr = {6, 6, 6, 6, 7, 7, 7, 7, 3, 3, 3};//6,4次。7,4次。3,3次。 // int i = onlyKTimes(arr, 3, 4); // System.out.println("i = " + i); // } }
标签:index,arr,int,range,num,Code03,出现,Math From: https://www.cnblogs.com/TheFloorIsNotTooHot/p/16838688.html