笔试算法题(15):-1到N中包含1的数字的个数 & 连续和为N的序列

出题:输入一个整数N,求从1到N这N个整数的十进制表示中‘1’出现的次数;

分析:

  • 从左向右处理string表示的数字;当前数字长度为n,判断最左边一位数字字符;
  • 如果是0,则直接递归下一位;
  • 如果是1,则计数有两个来源,一个是n位数数字(实际就是除去最高位之后的数字大小,加上1,当其余位全部为0的时候),另一个是n-1,n-2,……,1位数字,使用SpecialPower可以计算;
  • 如果是其他数字,则计数有两个来源,一个是n,n-1,n-2,……,1位数字,使用SpecialPower可以计算,另一个是去除最高位之后的数字大小;

解题:

 1 int NonRecursiveStrInt(char *target) {
 2         int sum=0;
 3         char *index=target;
 4 
 5         while(*index != '\0') {
 6                 sum*=10;
 7                 sum+=*index-'0';
 8                 index++;
 9         }
10 
11         return sum;
12 }
13 
14 int SpecialPower(int n) {
15         int sum=0;
16         int product;
17         for(int i=0;i<n;i++) {
18                 product=1;
19                 for(int j=0;j<i;j++) {
20                         product=product*10;
21                 }
22                 sum+=product;
23         }
24         return sum;
25 }
26 
27 int count1Decimal2(char *decimal,int n) {
28         if(*decimal == '\0') return 0;
29         if(*decimal == '0') return count1Decimal2(++decimal,n-1);
30         if(*decimal == '1')
31                 return NonRecursiveStrInt(++decimal) + 1 + SpecialPower(n-1);
32         return SpecialPower(n) + count1Decimal2(++decimal,n-1);
33 }
34 
35 int main() {
36         char *decimal="16";
37         printf("\n%d\n",count1Decimal2(decimal,2));
38         return 0;
39 }

 

出题:输入一个正整数N,求所有和为N的连续正整数序列

分析:

  • 橡皮筋解法,left和right为两端,当和小于N的时候右移right,当和大于N的时候左移left;
  • 另外还有求等差数列和解法(2N的分解因子):a+(a+1)+……+(a+k)=N,则有a(k+1)+(k+1)k/2=N,则有(k+2a)(k+1)=2N,a和k需为整数,简单枚举即可;

解题:

 1 int getSum(int start, int end) {
 2         int sum=0;
 3         for(int i=start;i<=end;i++) {
 4                 sum+=i;
 5         }
 6         return sum;
 7 }
 8 /**
 9  * left表示序列开始,right表示序列结束,
10  * 初始化left为1,right为2
11  * 每当找到一个序列之后,需要重新初始化left和right
12  * 连续和至少两个数,所以left的最大值不能大于(n+1)/2
13  * 当和小于n则增大left表示加入数字
14  * 当和大于n则增大right表示减去数字
15  * */
16 void SucceSum(int n) {
17         if(n<=2) {
18                 printf("\nn is less than 2\n");
19                 return;
20         }
21         int left=1;
22         int right=2;
23 
24         int mark=(n+1)/2;
25         int temp;
26         while(left<mark) {
27                 temp=getSum(left, right);
28                 if(n < temp) {
29                         left++;
30                 } else if(n > temp) {
31                         right++;
32                 } else {
33                         printf("new sequence: \n");
34                         for(int i=left;i<=right;i++) {
35                                 printf("%d, ",i);
36                         }
37                         printf("\n");
38                         left++;
39                         right=left+1;
40                 }
41         }
42 }

 

转载于:https://www.cnblogs.com/leo-chen-2014/p/3738443.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值