以下代码均是通过挑战的,可能有更好方式实现或是思路,容有时间再作考虑,请不吝指正赐教,在此多谢了。
题目1
有两个容器,容积分别为A升和B升,有无限多的水,现在需要C升水。 我们还有一个足够大的水缸,足够容纳C升水。起初它是空的,我们只能往水缸里倒入水,而不能倒出。 可以进行的操作是: 把一个容器灌满; 把一个容器清空(容器里剩余的水全部倒掉,或者倒入水缸); 用一个容器的水倒入另外一个容器,直到倒出水的容器空或者倒入水的容器满。 问是否能够通过有限次操作,使得水缸最后恰好有C升水。 输入:三个整数A, B, C,其中 0 < A , B, C <= 1000000000 输出:0或1,表示能否达到要求。
解:
c=i*a+j*b+m*(a+b)+n*(a-b) i,jm,n属于整数。gcd(a,b)表示a和b 最大公约数。
code:
public static boolean can(int a,int b,int c){
boolean flag=false;
int gcd_1=getGCD(a,b);
if(c%gcd_1==0||c%(2*gcd_1)==0){
flag=true;
}else{
if(Math.abs(a-b)!=0){
if(c%Math.abs(a-b)%a==0||c%Math.abs(a-b)%b==0){
flag=true;
}
}
if(c%(a+b)%a==0||c%(a+b)%b==0){
flag=true;
}
}
return flag;
}
/**
* 取最大公约数
* @param a
* @param b
* @return
*/
public static int getGCD(int a,int b){
if(b==0){
return a;
}
return getGCD(b,a%b);
}
public static void main(String[] args){
int[] c=new int[26];
System.out.println(getGCD(1234567,7654321));
boolean f=can(12,76,9999999);
System.out.println(f);
}
【2016-09-23 重写 公约数算法】
public static int gdc(int a,int b){
while(b!=0){
int temp = b;
b = a % b;
a = temp;
}
return a;
}
题目2
给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数组长度不超过100。 例如: 原数组是3,2,1, 我们只需要交换1和3就行了,交换次数为1,所以输出1。 原数组是2,3,1,我们需要交换2和1,变成1,3,2,再交换3和2,变为1,2,3,总共需要的交换次数为2,所以输出2。
解:
插入排序的思想,遍历a数组,取元素i与 i+i,i+2...(a.length-1)的元素比较交换。下标1的位置要找到元素中最小的元素,下标2的找次小的元素交换,以此类推。
code:
import java.util.Arrays;
public class ArrSortCnt {
public static int run(int[] a){
System.out.println("排序前数组:"+Arrays.toString(a));
int count=0;
for(int i=0;i<a.length;i++){
int temp=a[i];
int j=i+1;
int swapIndex=i;
while(j<a.length){
if(temp>a[j]){
temp=a[j];
swapIndex=j;
}
j++;
}
if(temp!=a[i]){
count++;
}
a[swapIndex]=a[i];
a[i]=temp;
}
System.out.println("排序后数组:"+Arrays.toString(a));
return count;
}
public static void main(String[] args){
int a[] = {10,2,8,7,6,5,4,3,9,1};
int cnt=run(a);
System.out.println(cnt);
}
}
题目3:
我们要给每个字母配一个1-26之间的整数,具体怎么分配由你决定,但不同字母的完美度不同, 而一个字符串的完美度等于它里面所有字母的完美度之和,且不在乎字母大小写,也就是说字母F和f的完美度是一样的。 现在给定一个字符串,输出它的最大可能的完美度。 例如:dad,你可以将26分配给d,25分配给a,这样整个字符串最大可能的完美度为77。
解:
计数排序的思想,记录数组a中的元素个数,元素最大的*26,次之*25,以此类推。
code:
import java.util.Arrays;
public class PerfectChar {
public static int perfect(String s){
s=s.toLowerCase();
char[] chs=s.toCharArray();
int[] cnts=new int[chs.length];
Arrays.fill(cnts,1);
for(int i=0;i<chs.length;i++){
if(cnts[i]==0){
continue;
}
for(int j=i+1;j<chs.length;j++){
if(chs[j]==chs[i]){
cnts[i]++;
cnts[j]=0;
}
}
}
Arrays.sort(cnts);
int total=0;
int maxVal=26;
for(int i=cnts.length-1;i>=0;i--){
total+=maxVal*cnts[i];
maxVal--;
}
return total;
}
public static void main(String[] args){
String a="abcc";
int total=perfect(a);
System.out.println(total);
}
}
以下代码未通过挑战,未发现问题,先贴上来,有时间再作修改。
题目4:
回文字符串是指从左到右和从右到左相同的字符串,现给定一个仅由小写字母组成的字符串,你可以把它的字母重新排列,以形成不同的回文字符串。 输入:非空仅由小写字母组成的字符串,长度不超过100; 输出:能组成的所有回文串的个数(因为结果可能非常大,输出对1000000007取余数的结果)。 例如:输入"aabb" 输出为2(因为“aabb”对应的所有回文字符串有2个:abba和baab)
【2017-01-05 修改】
分析:
CODE :
/**
* 回文字符总数
* @param str 仅由小写字母组成
* @return
*/
public int getPalindromicCount(String str){
int[] c = new int[26];
char[] chs = str.toCharArray();
for(int i =0;i<chs.length;i++){
c[chs[i]-97]++;
}
int result = 0;
if(!isNotPalindromic(c)){
result = calculate(c,chs.length);
}
System.out.println("结果:"+result);
return result;
}
/**
* 计算排列A(m+n+k,m+n+k)/(A(m,m)*A(n,n)*A(k,k))
* @return
*/
public int calculate(int[] c,int strLen){
double t = factorial(strLen/2);
double m = 1;
for(int i =0;i<c.length;i++){
if( c[i]!=0){
int n = c[i]/2;
m *= factorial(n);
}
}
int result = (int)(t/m%1000000007);
return result;
}
/**
* 阶乘
* @param n
* @return
*/
public double factorial(int n){
if(n<=0){
return 1;
}
return factorial(n-1)*n;
}
/**
* 是否可以构成回文字符
* <p>
* 统计的字母个数,如果奇数位的个数>1,则不能构成回文。
* 比如 字符aaabbb(3*a3*b),奇数位>1,所以不能构成回文。
* </p>
* @param c
* @return
*/
public boolean isNotPalindromic(int[] c){
int odd = 0;
for(int i =0;i<c.length;i++){
if ((c[i]&1) == 1){
odd++;
}
}
return (odd>1);
}
结果:
输入:aaabbb
返回: 0
输入:aabb
返回:2
输入: aab
返回: 1
输入: a
返回: 1
输入: aaaa
返回: 1