数字与数学基础问题

关卡名

数字与数学基础问题

我会了✔️

内容

1.数字里统计的处理技巧

✔️

2.必须熟练掌握溢的处理方法

✔️

3.掌握进制的处理方法

✔️

1. 数字统计专题 

统计一下特定场景下的符号,或者数字个数等是一类非常常见的问题 。如果按照正常方式强行统计,可能会非常复杂,所以掌握一些技巧是非常必要的。

1.1 符号统计

LeetCode1822 给定一个数组,求所有元素的乘积的符号,如果最终答案是负的返回-1,如果最终答案是正的返回1,如果答案是0返回0。
仔细分析一下这道题目,如果将所有数都乘起来,再判断正负,工作量真不少,而且还可能溢出。我们发现,一个数如果是 -100 和 -1,对符号位的贡献是完全一样的,所以只需要看有多少个负数,就能够判断最后乘积的符号了。

public int arraySign(int[] nums) {                           
    int prod = 1;                       
    for(int i = 0; i < nums.length; ++i) {     
        if(nums[i] == 0) {               
            return 0;//一切归零
        }else if(nums[i] < 0) {
        //交替就够了,很好的处理技巧
            prod = -prod;
        }
     }
     return prod;       
}

1.2 阶乘0的个数

很多数学相关算法的关键在于找到怎么通过最简洁的方式来解决问题,而不是硬算。例如:面试题16.05:设计一个算法,算出 n 阶乘有多少个尾随零。
这个题如果硬算,一定会超时,其实我们可以统计有多少个 0,实际上是统计 2 和 5 一起出现多少对,不过因为 2 出现的次数一定大于 5 出现的次数,因此我们只需要检查 5 出现的次数就好了,那么在统计过程中,我们只需要统计 5、10、15、 25、 ... 5^n 这样 5 的整数倍项就好了,最后累加起来,就是多少个 0。代码就是:

public int trailingZeroes(int n) {
        int cnt = 0;
        for (long num = 5; n / num > 0; num *= 5) {
            cnt += n / num;
        }
        return cnt;
}

数学不仅与算法难以区分 ,很多算法问题还与位运算密不可分,有些题目真不好说是该归类到数学中呢,还是位运算中。我们干脆就放在一起来看。

2 溢出问题 

溢出问题是一个极其重要的问题,只要涉及到输出一个数字,都可能遇到,典型的题目有三个:数字反转,将字符串转成数字和回文数。 不过溢出问题一般不会单独考察,甚至面试官都不会提醒你,但他就像捕捉猎物一样盯着你,看你会不会想到有溢出的问题。

2.1 整数反转

LeetCode7 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] ,就返回 0。假设环境不允许存储 64 位整数(有符号或无符号)。

输入:x = 123 输出:321

输入:x = -123 输出:-321

输入:x = 120 输出:21

输入:x = 0 输出:0

这个题的关键有两点,一个是如何进行数字反转,另一个是如何判断溢出。反转好说,那为什么会有溢出问题呢?例如1147483649这个数字,它是小于最大的32位整数2147483647的,但是将这个数字反转过来后就变成了9463847411,这就比最大的32位整数还要大了,这样的数字是没法存到int里面的,所以就溢出了。
首先想一下,怎么去反转一个整数。用栈?或者把整数变成字符串再反转字符串?都可以但都不好。我们只要一边左移一边处理末尾数字就可以了。以12345为例,先拿到5,再拿到4,之后是3,2,1,然后就可以反向拼接出一个数字了。那如何获得末尾数字呢?好办,循环取模运算即可。例如:

1.将12345 % 10 得到5,之后将12345 / 10=1234

2.将1234 % 10 得到4,再将1234 / 10=123

3.将123 % 10 得到3,再将123 / 10=12

4.将12 % 10 得到2,再将12 / 10=1

5.将1 % 10 得到1,再将1 / 10=0

画成图就是:

 

这样的话,是不是将循环的判断条件设为x>0就可以了呢?不行!因为忽略了负数的问题,应该是while(x!=0)。去掉符号,剩下的数字,无论正数还是负数,按照上面不断的/10这样的操作,最后都会变成0,所以判断终止条件就是!=0。有了取模和除法操作,就可以轻松解决第一个问题,如何反转。
接下来看如何解决溢出的问题。我们知道32位最大整数是MAX=2147483647,如果一个整数num>MAX,那么应该有以下规律:
nums/10 > MAX/10=214748364,也就是如果底数第二位大于4了,不管最后一位是什么都已经溢出了,如下:

所以我们要从到最大数的1/10时,就要开始判断,也即:

  • 如果 num>214748364 那后面就不用再判断了,肯定溢出了。
  • 如果num= 214748364,这对应到上图中第三、第四、第五排的数字,需要要跟最大数的末尾数字比较,如果这个数字比7还大,说明溢出了。
  • 如果num<214748364,则没问题,继续处理。

这个结论对于负数也是一样的,所以实现代码就是:

public int reverse(int x) {
        int res = 0;
        while(x!=0) {
            //获得末尾数字
            int tmp = x%10;
            //判断是否大于最大32位整数,也可以使用Integer.MAX_VALUE/10来代替214748364
            if (res>Integer.MAX/10 || (res==Integer.MAX/10 && tmp>7)) {
                return 0;
            }
            //判断是否小于最小的32位整数
            if (res<-214748364 || (res==-214748364 && tmp<-8)) {
                return 0;
            }
            res = res*10 + tmp;
            x /= 10;
        }
        return res;
}

2.2 字符串转整数 

LeetCode8.意思就是字符串转整数(atoi函数),题目比较长,解决过程中要涉及很多异常情况的处理,我们在《字符串》一关进行了详细讲解,请回顾一下相关的内容。

2.3 回文数

LeetCode9 .给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。

思路解析:
映入脑海的第一个想法是将数字转换为字符串,并检查字符串是否为回文。但是,这需要额外的非常量空间来创建问题描述中所不允许的字符串。
第二个想法是将数字本身反转,然后将反转后的数字与原始数字进行比较,如果它们是相同的,那么这个数字就是回文。 但是,如果反转后的数字大于int.MAX,我们将遇到整数溢出问题。
按照第二个想法,为了避免数字反转可能导致的溢出问题,为什么不考虑只反转 int 数字的一半?毕竟,如果该数字是回文,其后半部分反转后应该与原始数字的前半部分相同。
例如,输入 1221,我们可以将数字 “1221” 的后半部分从 “21” 反转为 “12”,并将其与前半部分 “12” 进行比较,因为二者相同,我们得知数字 1221 是回文。
这个反转思路与链表的反转是一样的,不过要简单多了。
这里还不能忘的问题就是,反转之后数字可能会溢出,因此必须做防范,方法我们上面说了,这里我们可以进一步简化一下:

public boolean isPalindrome(int x) {
    // 特殊情况:
    // 如上所述,当 x < 0 时,x 不是回文数。
    // 同样地,如果数字的最后一位是 0,为了使该数字为回文,
    // 则其第一位数字也应该是 0
    // 只有 0 满足这一属性
    if(x<0 || (x%10==0 && x!=0)){
        return false;
    }
    int revertedNumber = 0;
    while(x > revertedNumber){
        revertedNumber = revertedNumber*10 + x%10;
        x /= 10;
    }
    // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
    // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
    // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
    return x==revertedNumber x==revertedNumber /10;
}

3.进制专题 

进制问题也是一个非常重要的专题,有的直接处理还挺费劲,我们看两道题。

3.1 七进制数

LeetCode504.给定一个整数 num,将其转化为 7 进制,并以字符串形式输出。其中-10^7 <= num <= 10^7。

示例1:

输入: num = 100

输出: "202"

我们先通过二进制想一下7进制数的变化特征。在二进制中,先是0,然后是1,而2就是10(2),3就是11(2),4就是(100)。同样在7进制中,计数应该是这样的:
0 1 2 3 4 5 6 10 11 12 13 14 15 16 20 21 22 ...
给定一个整数将其转换成7进制的主要过程是循环取余和整除 ,最后将所有的余数反过来即可。例如,将十进制数100 转成七进制:

100÷7=14 余 2

14÷7=2 余 0

2÷7=0 余 2

向遍历每次的余数,依次是 2、0、2,因此十进制数 100 转成七进制数是202 。如果num<0,则先对 num 取绝对值,然后再转换即可。使用代码同样可以实现该过程,需要注意的是如果单纯按照整数来处理会非常麻烦,既然题目说以字符串形式返回,那我们干脆直接用字符串类,代码如下:

 

public String convertToBase7(int num) {
        StringBuilder sb = new StringBuilder();
        //先拿到正负号
        boolean sign = num < 0;
        //这样预处理一下,后面都按照正数处理num就行了
        if(sign)
            num *= -1;
        //循环取余和整除    
        do{
            sb.append(num%7 + "");
            num/=7;
        }while(num > 0);
        //添加符号
        if(sign)
            sb.append("-");
         //上面的结果是逐个在末尾加的,需要反过来   
        return sb.reverse().toString();
}

3.2 进制转换 

给定一个十进制数M,以及需要转换的进制数N,将十进制数M转化为N进制数。M是32位整数,2<=N<=16。
这个题目的思路不复杂,但是想写正确却很不容易,甚至越写越糊涂。本题有好几个需要处理的问题:

  • 1.超过进制最大范围之后如何准确映射到其他进制,特别是ABCDEF这种情况。简单的方式是大量采用if 判断,但是这样会出现写了一坨,最后写不下去。
  • 2.需要对结果进行一次转置。
  • 3.需要判断负号。

下面这个是我总结出的最精简,最容易理解的实现方案。注意采取三个措施来方便处理:

  • 1.定义大小为16的数组F,保存的是2到16的各个进制的值对应的标记,这样赋值时只计算下标,不必考虑不同进制的转换关系了。
  • 2.使用StringBuffer完成数组转置等功能,如果不记得这个方法,工作量直接飙升。
  • 3.通过一个flag来判断正数还是负数,最后才处理。
  // 要考虑到 余数 > 9 的情况,2<=N<=16.
    public static final String[] F = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
   //将十进制数M转化为N进制数
    public String convert (int M, int N) {
       Boolean flag=false;
        if(M<0){
            flag=true;
            M*=-1;
        }
        StringBuffer sb=new StringBuffer();
        int temp;
        while(M!=0){
            temp=M%N;
            //技巧一:通过数组F[]解决了大量繁琐的不同进制之间映射的问题
            sb.append(F[temp]);
            M=M/N;
        }
        //技巧二:使用StringBuffer的reverse()方法,让原本麻烦的转置瞬间美好
        sb.reverse();
        //技巧三:最后处理正负,不要从一开始就揉在一起。
        return (flag? "-":"")+sb.toString();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/216434.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯物联网竞赛_STM32L071_9_按键矩阵扩展模块

原理图&#xff1a; 矩阵按键原理图&#xff1a; 实验板接口原理图&#xff1a; 得到对应图&#xff1a; 扫描按键原理&#xff1a; 按键的COLUMN1、2、3分别制0&#xff0c;每次只允许其中一个为0其他都是1&#xff08;POW1和POW2正常状况为上拉&#xff09;&#xff0c;当有…

S32K116新建工程Debug可以运行,冷启动无法运行问题分析

S32K116使用IAR建立工程后&#xff0c;软件debug可以运行&#xff0c;断电冷启动无法运行。 这种现象基本上都是RAM未初始化导致&#xff0c;由于Debug时&#xff0c;调试器会自动初始化芯片&#xff0c;很多问题都不会暴露处理。 大家可以开一下Startup的汇编文件&#xff0c;…

LInux组管理及拓展

目录 一、Linux组管理 &#xff08;一&#xff09;、组的概述 1.概述 2.作用 &#xff08;二&#xff09;、组操作 1.创建 2.修改 3.删除 4.添加用户 二、用户信息查看 &#xff08;一&#xff09;、id &#xff08;二&#xff09;、finger &#xff08;三&#x…

Go 语言中的函数调用。

更好的观看体验&#xff0c;请点击——函数调用 | YinKais Blog 本文将从函数的调用惯例和参数传递方法两个方面分别介绍函数执行的过程。 1、调用惯例 对于不同的编程语言&#xff0c; 它们在调用函数的时候往往都使用相同的语法&#xff1a; somefunction(arg0, arg1) 虽…

你离高级开发只差这些IntelliJ IDEA Debug使用技巧

目录 引言 IntelliJ IDEA&#xff0c;由JetBrains&#xff08;捷克共和国&#xff09;开发的一款强大的Java集成开发环境&#xff08;IDE&#xff09;&#xff0c;因其丰富的功能、智能的代码辅助以及用户友好的界面设计&#xff0c;在全球范围内广受Java开发者的喜爱&#xf…

VPS服务器”性价比之王”系列:RackNerd

2023 黑五&#xff01;&#xff01;&#xff01;新 Ryzen 系列 洛杉矶dc02机房重新补货&#xff01; 支付方式&#xff1a;支付宝、PayPal、信用卡、数字货币 2023 黑五促销活动&#xff08;限量&#xff09; CPU内存硬盘(SSD)流量带宽价格(续费同价)购买链接1核768 MB15GB…

“数”说新语向未来 | GBASE南大通用2023媒体交流会成功举办

在当前国家信创战略加速实施&#xff0c;及国民经济数字化转型&#xff0c;叠加驱动信息化行业加速发展的大形势下&#xff0c;以“数说新语-GBASE南大通用开放创新再领航”为主题的2023 GBASE南大通用媒体交流日活动在GBASE天津总部举行。来自IT168、ITPUB、韩锋频道、自主可控…

freeRTOS创建任务

一.动态创建任务 1.函数xTaskCreate() BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数const char * const pcName, // 任务的名字const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节void * const pvParameters, // …

elment-table设置el-table-column的label里面的文字换行居中显示

效果图如下&#xff1a; 直接上代码&#xff1a; <el-table class"ut-mt-2" row-key"company" default-expand-all:data"stateQuery.data" style"width: 100%":tree-props"{ children: departList, hasChildren: hasChildre…

Java 设计模式——备忘录模式

目录 1.概述2.结构3.案例实现3.1.“白箱”备忘录模式3.2.”黑箱”备忘录模式 4.优缺点5.使用场景 1.概述 &#xff08;1&#xff09;备忘录模式 (Memento Pattern) 又称为快照模式&#xff0c;是一种行为型设计模式&#xff0c;它提供了一种保存和恢复对象状态的机制。备忘录模…

Vue3使用vue-baidu-map-3x百度地图

安装vue-baidu-map-3x&#xff1a; // vue3 $ npm install vue-baidu-map-3x --save// vue2 $ npm install vue2-baidu-map --save 全局注册/局部注册&#xff1a; import { createApp } from vue import App from ./App.vue import BaiduMap from vue-baidu-map-3xconst app …

SpringBoot 注入RedisTemplat 启动报错

需求 因为需要限制部门内多个人员同一时间操作同一批客户的需求&#xff0c;考虑下决定用Redis滑动窗口实现自过期以及并发校验。 问题 新建了个Redis工具类封装RedisTemplat 操作&#xff0c;到启动时却发现无法正常启动&#xff0c;报错注入错误。 The injection point has…

leetcode做题笔记1038. 从二叉搜索树到更大和树

给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff1a; 节点的左子树仅包含键 小于 节点键的节点。节点的右子树仅包含键 大于 节点键的节点。左右…

Spring 概述

1 了解Spring框架 1.1 框架 框架&#xff0c;特指为解决一个开放性问题而设计的具有一定约束性的基础架构。在此架构上可以根据具体问题进行扩展和定制&#xff0c;添加更多的组成部分&#xff0c;从而更迅速和方便地构建完整的解决问题方案。 框架&#xff0c;是一种可重用…

spark无法执行pi_如何验证spark搭建完毕

在配置yarn环境下的spark时&#xff0c;执行尚硅谷的以下命令发现报错&#xff0c;找不到这个也找不到那个&#xff0c;尚硅谷的代码是 bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master yarn \ --deploy-mode cluster \ ./examples/jars/spark-exam…

初试占比7成!只考一门数据结构+学硕复录比1:1的神仙学校,大连交通大学考情分析

大连工业大学 考研难度&#xff08;☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、24专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1014字&#xff0c;预计阅读&#xff1a;3分钟 2023考情概况 大连工业…

企业电子招投标系统源码之电子招投标系统建设的重点和未来趋势

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

中危漏洞!小程序优惠卷遍历

进入小程序&#xff0c;因为是一个小商城&#xff0c;所以照例先查看收货地址是否存在越权&#xff0c;以及能否未授权访问&#xff0c;但是发现不存在这些问题&#xff0c;所以去查看优惠卷 进入领券中心&#xff0c;点击领取优惠券时抓包 发现数据包&#xff0c;存在敏感参数…

【android开发-14】android中fragment用法详细介绍

1&#xff0c;fragment是什么&#xff1f; Fragment是Android中的一种组件&#xff0c;它在Android 3.0&#xff08;API级别11&#xff09;及以后的版本中引入。Fragment可以用来在Activity中添加一个或多个具有自己的用户界面的片段。它们可以与Activity进行交互&#xff0c;并…

MS8231/8232微功耗、高精度、轨到轨输入输出运算放大器

产品简述 MS8231/8232 是单通道、双通道的轨到轨输入输出单电源运 放。它们具有很低的功耗和较高的精度&#xff0c;很适合电池供电和便携 式电子系统。 MS8231/8232 具有稳定的单位增益特性&#xff0c;并具有 13kHz 的信 号带宽&#xff0c;使其适合电池电流检测和传…