网易编程 混合颜料(异或操作)

题目描述

你就是一个画家!你现在想绘制一幅画,但是你现在没有足够颜色的颜料。为了让问题简单,我们用正整数表示不同颜色的颜料。你知道这幅画需要的n种颜色的颜料,你现在可以去商店购买一些颜料,但是商店不能保证能供应所有颜色的颜料,所以你需要自己混合一些颜料。混合两种不一样的颜色A和颜色B颜料可以产生(A XOR B)这种颜色的颜料(新产生的颜料也可以用作继续混合产生新的颜色,XOR表示异或操作)。本着勤俭节约的精神,你想购买更少的颜料就满足要求,所以兼职程序员的你需要编程来计算出最少需要购买几种颜色的颜料?

输入描述:

第一行为绘制这幅画需要的颜色种数n (1 ≤ n ≤ 50)
第二行为n个数xi(1 ≤ xi ≤ 1,000,000,000),表示需要的各种颜料.

输出描述:

输出最少需要在商店购买的颜料颜色种数,注意可能购买的颜色不一定会使用在画中,只是为了产生新的颜色。
示例1

输入

3
1 7 3

输出

3

java代码:

package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Color {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
ArrayList<Integer>  list=new ArrayList<Integer>();
int n=sc.nextInt() //定义需要多少种颜色
for(int i=0;i<n;i++)
{
list.add(sc.nextInt());
}
Collections.sort(list);//首先对列表中的数字进行排序
int result=0;
int endNumber=list.size()-1; //endNumber、preEndNumber始终指向的是最后一位和倒数第二位数
int preEndNumber=endNumber-1;

while(list.size()>2)
{   
int temp;

//如果两者的最高位相同,说明最高位可以消掉,如果两者的最高位相同,说明最高位可以消掉
if(getHight(list.get(endNumber))==getHight(list.get(preEndNumber)))  
{
temp=list.get(endNumber)^list.get(preEndNumber);

// 因为现在 xor 的是两个最大的数,而且最高位已被消掉,所以 xor 得到的结果一定比这两个数小
                // 如果 temp 这个 比最大两个数小的 数没有被找到,则将 temp 加到 colors 数组中,进行再次 xor
if(!list.contains(temp))
{
list.add(temp);
endNumber++;
preEndNumber++;
Collections.sort(list);
}
}else
{
result++;
}

 // 如果两者最高位不同,说明已经所有数的最高位已经只有最大的那个数是 1 了,这样它已经不可能被消掉了,结果+ 1
            // 如果两个最大数的最高位可以消掉,那么消除之后,最大数已被消掉,没有用了
            // 如果两个最大数的最高位不可以消掉,那么结果+ 1 ,最大数也没有用了。
list.remove(list.size()-1);
   endNumber=preEndNumber;
   preEndNumber--;
   
}
System.out.println(list.size()+result);
}

//判断最高位的函数
public static int getHight(int num)
{
int k=0;
while(num>0)
{
num>>=1;
k++;
}
return k;
}
}

注释:最大两个数最高位不同(也即最左边1的位数不同),则大的最左边位置为1,小的相应位为0,显然最大的是不能被合成的(除自己外,再没有相应位为1的啊),而且它也不能合成其它数(其它数相应位都为0啊),故此时将最大数直接丢弃,所需的颜料数加一。若最高位相同,则对两数异或,合成的数(一定比当前合成它的两数小)若不存在,则添加入初始颜料数中并排序(以待合成其它数),无论合成的数是否存在,都要删掉最后一个数,因为它是可以被合成的(A(最大)^B(次大)=C(合成数),B^C=A(最大数))。总之最后一个数(排序后)每比操作一次都要舍弃掉

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值