内容五
分析:一次只能选一个数。
1.找到所有值相等的偶数
2.找到所有偶数
3.如果只是需要输出次数的话,可以倒入集合里去除重复元素,减少数字的数量,然后找到所有偶数,算出每个偶数变成奇数所需要的次数相加就行。
4.奇数,二进制最后一位是1;偶数二进制最后一位是0,看这个偶数(二进制形式)左移多少位最后一位能变成1就行。
按以上的思路测试出来的结果不对。
因为,每移位一次得到的结果都可能变成一个与集合里重复的偶数。
所以每移动一次都要更新一次集合。
经过又一轮测试之后,发现要从最大偶数的开始变成除2,才能保证最小次数。
思路:
第一次输入时判断是否为偶数,不是偶数则丢弃,是则放入集合中
集合里都是偶数并且没有重复,我们每次取出集合里的最大的数,进行左移一位,如果还是偶数,删除原来的数并将新的移位好的数写入集合(写入的时候集合会自动去重) 如果移位后变成奇数就直接从集合里删除这个数
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
/**
* @author SJ
* @date 2020/10/28
*/
public class EvenToOdd {
public static Set<Integer> nums;//用于存放输入的数字
public EvenToOdd(int length) {
nums = new HashSet<>();
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < length; i++) {
int temp = scanner.nextInt();
//判断一下,是奇数的话就没有必要往集合里放了。
if (isEven(temp))
nums.add(temp);
}
}
public static int evenToOdd() {
int times = 0;
/* Iterator<Integer> iterator = nums.iterator();
if (iterator.hasNext()) {
Integer num = iterator.next();
if (isEven(num)) {
//二进制字符串,从后往前找第一个位置为1的地方
String string = Integer.toBinaryString(num);
char[] chars = string.toCharArray();
for (int i = chars.length - 2; i >= 0; i--) {
if (chars[i] == '1') {
int time = chars.length - 1 - 1;
num =<<time;
break;
}
}
}
}*/
//此时集合里都是偶数并且没有重复,我们每次取出集合里的最大的数,进行左移一位,如果还是偶数,删除原来的数并将
//新的移位好的数写入集合(写入的时候集合会自动去重)
//如果移位后变成奇数就直接从集合里删除这个数
while (nums.size() != 0) {
int temp = 0;
Iterator<Integer> iterator1 = nums.iterator();
int max = findMax(nums);
while (iterator1.hasNext()) {
Integer theNum = iterator1.next();
//找到最大值后
if (theNum == max) {
temp = theNum >> 1;
iterator1.remove();
times++;
}
}
if (isEven(temp) && temp != 0)
nums.add(temp);
}
return times;
}
//判断是否为偶数
public static Boolean isEven(Integer a) {
if (a % 2 == 0)
return true;
return false;
}
//找出集合中的最大值
public static int findMax(Set<Integer> set) {
int max = Integer.MIN_VALUE;
for (Integer integer : set) {
if (integer > max)
max = integer;
}
return max;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
new EvenToOdd(i);
int i1 = evenToOdd();
System.out.println("需要的次数为:" + i1);
}
}
测试:
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"...
6
40 6 40 3 20 1
需要的次数为:4
Process finished with exit code 0
算法分析:时间主要花在:遍历集合寻找最大值上,不过好在集合里都是偶数且没有重复数字。时间取决于输入的序列里偶数的个数。
假设结果是最小需要n次的话,那么需要遍历2*n次集合(第一遍用于找最大值,第二遍用于匹配到最大值然后进行删除或者更新操作)
集合没有下标进行定位,所以必须得遍历两遍,这也算是一个缺点吧,但是它去重的功能可以大大减少我们的工作量,总的来说我觉得是好处大于坏处的。