Google 2018 Problem A Even digits 题解

Problem A: Even Digits

题目理解

  • 输入:任意正数
  • 要求:对数据进行加一或减一的操作,使每一位都为偶数
  • 输出:操作次数

例如:11=>3 (11-1-1-1=8) 1=>1(1+1=2或1-1=0)

Google在kick start中会有大小两个数据集,这里面会要求我们对时间复杂度O有理解并且能大致估算时间(1s大概对应 1 0 9 10^{9} 109次操作)
Markdown下不能直接插入公式,我又主动逃避LaTeX的写法我好难呜呜呜

解题方法

  • 暴力解法

    暴力枚举,对数据直接+1或者-1判断是否符合题目要求

这里的代码完全参考了program中的mentor邝斌的代码
csdn代码块好难编辑

int getAns(int  N){
    for(int i = 0;;i++){
   		if(check(N-i)||check(N+i)){
   			return i;
   		}}
  • 优化题解

大:比N大的最小的满足题意的数
小:比N小的最大的满足题意的数
从最高位向下寻找第一个奇数

  1. 小于N的数

将第一个奇数-1并将之后的数归为8
例如
 2234424=>2228888
12422886=>08888888

缩进的tip:
在需要添加缩进的文字前面添加如下内容即可:(需将;替换成英文格式下的;)
空格间隙大小: >  >  >  

long long gerPre(long long n){//!大数据集的长度需要使用long long类型,否则会溢出    
	int cnt = 0//记录数字长度    
	int num[20]//存放每一位上的数字    
	do{        
		num[cnt++]==n%10;        
    		n/=10;    
   	}while(n);    
   	for(int i = cnt-1; i >= 0; i--){//最高位向后遍历 
  		if(num[i]&1){//按位与 1为偶数 0为负数              
     	 	num[i]--;//寻找小数奇数-1             
      		for(int j = i-1; j >=0; j--){                 
         		num[j] = 8;//之后的每项归为0            
      		}            
      		break//跳出循环,此时的num为符合题意的数          
  	}    
 }    
 long long ans = 0for(int i = cnt-1; i >= 0; i--){        
  ans = ans*10 + num[i];    
 }    
 return ans;
}

  1. 大于N的数

将第一个奇数+1并将之后的数归为0,但需要考虑奇数为9的特殊情况,当数字是9的时候,需要向前进1,所以我们分两种情况讨论。

  • 奇数非9
    该数+1,将之后的归为0,之前的保持不变。
    例如
     2234424=>2240000
  • 奇数为9
    该数为0,应该向前进1,但为了保持之前的偶数性质(修改的奇数为查找到的第一个奇数),之前的每位直接+2,若前一位有8,再向前一位+2.
    例如
     4249231=>4260000
     8889231=>20000000

这里完全参考了mentor 的代码

long long getNext(long long n){
	int cnt = 0;
	int num[20];
	do{
	    num[cnt++]=n%10;
	    n/=10;
	}while(n);
	num[cnt++] = 0;
	for(int i = cnt-1;i >= 0; i--){
	    if(num[i]&1){
	    	if(num[i] == 9){
		    int j = i+1;
  		    while(num[j]==8){
		    	j++;
		    }
		    num[j]+=2;
 		    while((--j) >= 0){
		    	num[j] = 0;
		    }
	   	}else{
	    	    num[i]++;
	    	    for(int j = i-1; j >= 0; j--){
	    	    	num[j]=0;
	    	    }
		}
		break;
	    }
	}
	long long ans = 0;
	for(int i = cnt -1; i >=0 ;i--){
		ans = ans*10 + num[i];
	}
	return ans;
}

脑洞题解
mentor提到的,可以将该题解理解为:将数据转换为一个五进制(五进制由0 2 4 6 8组成)
将每一位mod2后将结果+1,再将每一位乘2
例如
 8889231=>4444000=>4445000=>20000000

long long getNext(int n){
	int cnt = 0;
	int num[20];
	do{
	    num[cnt++]=n%10;
	    n/=10;
	}while(n);
 	for(int i = cnt - 1; i >= 0; i--){
   	    if(num[i]&1){
 	    	num[i] = num[i]/2 + 1;
 	    	for(int j = i-1; j >= 0; j--){
 	    	    num[j] = 0;
 	    	}
 	    	break;
 	    }
 	    else{
 	        num[i] = num[i]/2;
 	    }
 	}
 	int ans = 0;
 	for(int i = cnt - 1; i >= 0; i--){
 	    ans = ans*10 + num;
 	}
 	return 2*ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值