• 笔试算法题(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 != '') {
     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 == '') 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("
    %d
    ",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("
    n is less than 2
    ");
    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: 
    ");
    34                         for(int i=left;i<=right;i++) {
    35                                 printf("%d, ",i);
    36                         }
    37                         printf("
    ");
    38                         left++;
    39                         right=left+1;
    40                 }
    41         }
    42 }
  • 相关阅读:
    js中split()和join()的用法
    事件监听
    行内元素和块级元素
    parseInt()详解
    进制的转换
    什么叫优雅降级和渐进增强?
    js延迟加载的方式有哪些?
    javascript作用域和作用域链
    函数的原型对象和原型链?
    Tensorflow知识点学习
  • 原文地址:https://www.cnblogs.com/leo-chen-2014/p/3738443.html
Copyright © 2020-2023  润新知