剑指Offer第一章——整数

news2024/12/24 2:54:08

1. 整数

1.1 整数的基础知识

整数是一种基本的数据类型。编程语言可能会提供占据不同内存 空间的整数类型,每种类型能表示的整数的范围也不相同。例如,Java中有4种不同的整数类型,分别为8位的byte(-2^{7}2^{7}-1)、16位 的short(-2^{15}2^{15}-1)、32位的int(-2^{31}2^{31}-1)和64位的long(-2^{63}2^{63}-1)。

面试题1:整数除法

题目:输入2个int型整数,它们进行除法计算并返回商,要求 不得使用乘号'*'、除号'/'及求余符号'%'。当发生溢出时,返回最 大的整数值。假设除数不为0。例如,输入15和2,输出15/2的结 果,即7。

public class Offer_001_整数除法 {
    public static void main(String[] args) {
        System.out.println(divide(15, 7));
    }

    public static int divide(int dividend, int divisor) {
        // 当发生溢出时,返回最大的整数值
        if (dividend == Integer.MIN_VALUE && divisor == -1)
            return Integer.MAX_VALUE;

        // 将减数和被减数都转化成负数,因为负数的取值范围更大
        int negative = 2;
        if (dividend > 0) {
            negative--;
            dividend = -dividend;
        }
        if (divisor > 0) {
            negative--;
            divisor = -divisor;
        }

        // 计算结果并根据正负返回
        int result = divideCore(dividend, divisor);
        return negative == 1 ? -result : result;
    }

    public static int divideCore(int dividend, int divisor) {
        int result = 0;
        // 如果被减数 小于 减数一直循环,类似于快速幂
        // 这里要注意是小于,因为负数的小于就相当于正数的大于了
        while (dividend <= divisor) {
            int temp = divisor;
            int quotient = 1;
            // 防止溢出
            while (temp + temp >= Integer.MIN_VALUE && dividend <= temp + temp) {
                // 翻倍。
                temp += temp;
                quotient += quotient;
            }

            result += quotient;
            dividend -= temp;
        }

        return result;
    }
}

1.2 二进制

与、或和异或的运算规律如表1.1所示。

面试题2:二进制加法

题目:输入两个表示二进制的字符串,请计算它们的和,并以 二进制字符串的形式输出。例如,输入的二进制字符串分别
是"11"和"10",则输出"101"。

public class Offer_002_二进制加法 {
    public static void main(String[] args) {
        System.out.println(addBinary("101", "1"));
    }

    public static String addBinary(String a, String b) {
        StringBuilder stringBuilder = new StringBuilder();
        // 获取两个二进制字符串的长度,减一为下标
        int i = a.length() - 1;
        int j = b.length() - 1;
        // 存储进位
        int carry = 0;
        while (i >= 0 || j >= 0) {
            // 都从字符串末尾开始遍历
            int digitA = i >= 0 ? a.charAt(i--) - '0' : 0;
            int digitB = j >= 0 ? b.charAt(j--) - '0' : 0;
            // 计算该位的二进制之和
            int sum = digitA + digitB + carry;
            carry = sum >= 2 ? 1 : 0;
            // 如果进位则和 -2
            sum = sum >= 2 ? sum - 2 : sum;
            stringBuilder.append(sum);
        }
        // 判断最后是否有进位
        if (carry == 1)
            stringBuilder.append(carry);

        // 因为是从低位开始存的 所以返回是先反转
        return stringBuilder.reverse().toString();
    }
}

面试题3:前n个数字二进制形式中1的个数 

题目:输入一个非负数n,请计算0到n之间每个数字的二进制形 式中1的个数,并输出一个数组。例如,输入的n为4,由于0、1、2、3、4的二进制形式中1的个数分别为0、1、1、2、1,因此输出数 组[0,1,1,2,1]。 

public class Offer_003_前n个数字二进制形式中1的个数 {
    public static void main(String[] args) {
        System.out.println(Arrays.toString(countBits(11)));
    }

    public static int[] countBits(int n) {
        int[] result = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            // result[i] 为数字 i 有几个 ‘1’
            // 而result[i & (i - 1)] 比 result[i] 少 1 个
            result[i] = result[i & (i - 1)] + 1;
        }

        return result;
    }
}

 关于 i 与 i & (i-1):

        假设 i = 10,i 的二进制为 "1010",i - 1 的二进制为 "1001",故 i & (i - 1) 为 "1000",比 i 的二进制少了一个数字 '1'。


 面试题4:只出现一次的数字

题目:输入一个整数数组,数组中只有一个数字出现了一次,而其他数字都出现了3次。请找出那个只出现一次的数字。例如,如 果输入的数组为[0,1,0,1,0,1,100],则只出现一次的数字是 100。

分析:这个题目有一个简化版的类似的题目“输入数组中除一个 数字只出现一次之外其他数字都出现两次,请找出只出现一次的数 字”。任何一个数字异或它自己的结果都是0。如果将数组中所有数字 进行异或运算,那么最终的结果就是那个只出现一次的数字。

public class Offer_004_只出现一次的数字 {
    public static void main(String[] args) {
        System.out.println(singleNumber(new int[]{1, 0, 0, 1, 1, 0, 100}));
    }

    public static int singleNumber(int[] nums) {
        // int数值有32位,记录所有数字每一位之和
        int[] bitSums = new int[32];
        for (int num : nums) {
            for (int i = 0; i < 32; i++) {
                // 通过移位运算之后,与 1 进行 & 运算,只添加那一位上面的数值
                bitSums[i] += (num >> (31 - i)) & 1;
            }
        }

        // 计算结果,将每一位上面的数值之和存放至result变量中,并通过%3来处理出现过三次的数字,算得的结果就是只出现了一次的数字
        int result = 0;
        for (int i = 0; i < 32; i++) {
            result = (result << 1) + bitSums[i] % 3;
        }
        return result;
    }
}

举一反三

            题目:输入一个整数数组,数组中只有一个数字出现m次,其他数 字都出现n次。请找出那个唯一出现m次的数字。假设m不能被n整除。

分析:解决面试题4的方法可以用来解决同类型的问题。如果数组 中所有数字的第i个数位相加之和能被n整除,那么出现m次的数字的第 i个数位一定是0;否则出现m次的数字的第i个数位一定是1。


面试题5:单词长度的最大乘积

题目:输入一个字符串数组words,请计算不包含相同字符的两 个字符串words[i]和words[j]的长度乘积的最大值。如果所有字符 串都包含至少一个相同字符,那么返回0。假设字符串中只包含英文 小写字母。例如,输入的字符串数组words为
["abcw","foo","bar","fxyz","abcdef"],数组中的字符 串"bar"与"foo"没有相同的字符,它们长度的乘积为9。"abcw"与"fxyz"也没有相同的字符,它们长度的乘积为16,这是 该数组不包含相同字符的一对字符串的长度乘积的最大值。

分析:解决这个问题的关键在于如何判断两个字符串str1和str2 中没有相同的字符。一个直观的想法是基于字符串str1中的每个字符 ch,扫描字符串str2判断字符ch是否出现在str2中。如果两个字符串 的长度分别为pq,那么这种蛮力法的时间复杂度是Opq)。

优化:

用哈希表记录字符串中出现的字符

        也可以用哈希表来优化时间效率。对于每个字符串,可以用一个 哈希表记录出现在该字符串中的所有字符。在判断两个字符串str1和 str2中是否有相同的字符时,只需要从'a'到'z'判断某个字符是否在 两个字符串对应的哈希表中都出现了。在哈希表中查找的时间复杂度 是O(1)。

        这个题目假设所有字符都是英文小写字母,只有26个可能 的字符,因此最多只需要在每个字符串对应的哈希表中查询26次就能 判断两个字符串是否包含相同的字符。26是一个常数,因此可以认为 应用哈希表后判断两个字符串是否包含相同的字符的时间复杂度是 O(1)。

但是使用哈希表用来判断一个字符串中是否出现某个字符需要判断26次,还可以优化成一次。

用整数的二进制数位记录字符串中出现的字符

        前面的解法是用一个长度为26的布尔型数组记录字符串中出现的 字符。布尔值只有两种可能,即true或false。这与二进制有些类似,在二进制中数字的每个数位要么是0要么是1。因此,可以将长度为26 的布尔型数组用26个二进制的数位代替,二进制的0对应布尔值 false,而1对应true。

        Java中int型整数的二进制形式有32位,但只需要26位就能表示一 个字符串中出现的字符,因此可以用一个int型整数记录某个字符串中 出现的字符。如果字符串中包含'a',那么整数最右边的数位为1;如 果字符串中包含'b',那么整数的倒数第2位为1,其余以此类推。这样 做的好处是能更快地判断两个字符串是否包含相同的字符。如果两个 字符串中包含相同的字符,那么它们对应的整数相同的某个数位都为 1,两个整数的与运算将不会等于0。如果两个字符串没有相同的字 符,那么它们对应的整数的与运算的结果等于0。

代码如下👇:

public class Offer_005_单词长度的最大乘积 {
    public static void main(String[] args) {
        System.out.println(maxProduct(new String[]{"qwe", "dhdgf"}));
    }


    public static int maxProduct(String[] words) {
        // 只用一个int值来表示一个String中是否含有某个字符
        int[] flags = new int[words.length];
        for (int i = 0; i < words.length; i++) {
            for (char ch : words[i].toCharArray()) {
                // 使用 '|' 运算符来将它这个String中的字符存入int中。其中第一位如果是1,代表字符串含有'a',以此类推
                flags[i] |= 1 << (ch - 'a');
            }
        }

        int max = 0;
        for (int i = 0; i < words.length; i++) {
            for (int u = i + 1; u < words.length; u++) {
                // 遍历每一个字符串如果 & 运算的值为0,则说明没有含有一个同样的字符
                if ((flags[i] & flags[u]) == 0)
                    max = Math.max(max, words[i].length() * words[u].length());
            }
        }

        return max;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Minecraft 1.20.x Forge模组开发 04.动画效果物品

我们本次实现一个具有动画效果的流星锤: 效果演示 效果演示 效果演示 首先,请确保你的开发包中引入了geckolib依赖,相关教程请参考:Minecraft 1.20.x Forge模组开发 03.动画生物实体 1.首先我们要使用geckolib制作一个物品和对应的动画: 在blockbench中新建一个

Android TelephonyManager双卡获取数据开启状态异常的可能原因

背景 应用内不指定subId获取数据状态可能会错误&#xff0c;因为可能拿到voice的能力&#xff0c;而非data。 代码逻辑 1、通过TelephonyManager的isDataEnabled()没有指定subId时&#xff0c;调用内部方法isDataEnabledForReason&#xff0c;传入getId()参数以指定subid&am…

设备监测诊断与维护:优化工业生产效率的关键措施

在现代工业生产中&#xff0c;设备的稳定运行对于保障生产效率至关重要。设备监测、诊断和维护作为关键措施&#xff0c;能够帮助企业及时发现设备问题、诊断故障原因&#xff0c;并采取有效维护措施&#xff0c;从而降低生产中断风险&#xff0c;提高生产效率。本文将深入探讨…

【二叉树】利用前序和中序遍历结果生成二叉树并输出其后序和层序遍历结果

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; ⭐️往期关于树的文章&#xff1a; 【哈夫曼树】基本概念、构建过程及C代码 【线索二叉树】C代码及线索化过程详解 欢迎阅读&#xff01; 实验内容 根据二叉树先序和中序遍历的结果,生成该二叉树。并…

pytest自动化测试框架tep环境变量、fixtures、用例三者之间的关系

tep是一款测试工具&#xff0c;在pytest测试框架基础上集成了第三方包&#xff0c;提供项目脚手架&#xff0c;帮助以写Python代码方式&#xff0c;快速实现自动化项目落地。 在tep项目中&#xff0c;自动化测试用例都是放到tests目录下的&#xff0c;每个.py文件相互独立&…

低代码治好了CIO们的 “精神内耗”

目录 一、前言 二、低代码在企业数字化转型中能“C位出道”&#xff0c;凭什么&#xff1f; 三、低代码的数字化构建能力 四、结束语 一、前言 近两年&#xff0c;我发现身边的CIO/CTO朋友都得了一种“病”——“数字化焦虑”症。 他们经常皱着眉头问我&#xff1a;“老板对数字…

gradio初体验

背景 近期随着很多开源大模型的出现&#xff0c;对于其如何落地&#xff0c;或者说充分地去挖掘其实际应用领域和商业价值变得格外重要。于是乎&#xff0c;对于不懂技术的前方市场或销售人员&#xff0c;如何在没有形成AI产品之前向其展示算法模型效果呢&#xff1f;这时候gr…

【严重】Citrix ADC 和 Citrix Gateway 远程代码执行漏洞(PoC)

漏洞描述 Citrix ADC是应用程序交付和负载平衡解决方案&#xff0c;Citrix Gateway是一套安全的远程接入解决方案&#xff0c;常用于提供虚拟桌面和远程桌面服务&#xff0c;此外&#xff0c;Citrix ADC还被广泛用作Windows堡垒机。 在 Citrix ADC 和 Citrix Gateway 受影响版…

《我为什么要听你的 如何与强势的人相处》读书笔记二

目录 反驳例子 勇敢反击的益处 一些重要的自我保护法 不要再讲述你生活中的细节 别答应那些表意不明的请求 记录下一切 第一时间告知亲友 拒绝成为中间人 区别对待强势者 谨慎应对奉承话 想方设法快点跑 反驳例子 例子 例子&#xff1a; 例子&#xff1a; 例子&am…

什么是UE像素流送,像素流推流是什么原理?

游戏开发者通常在运行游戏逻辑时会将游戏渲染到屏幕的同一台设备上来运行虚幻引擎应用&#xff0c;多人联网游戏可能会在应用程序的多个实例之间分发部分游戏逻辑&#xff0c;但每个单独的实例仍然会为自己的玩家在本地渲染游戏。即使是使用 HTML5 部署选项创建可以在 Web 浏览…

CountDownLatch 一个神奇的计数器,您了解吗

一、CountDownLatch基础概念及案例 1.CountDownLatch是java.util.concurrent 包下提供一个同步工具类&#xff0c;它允许一个或多个线程一直等待&#xff0c;直到其他线程执行完成再执行。其本质就是一个计数器&#xff0c;传入一个初始的值&#xff0c;调用await 方法会阻塞当…

vue+Element项目中v-for循环+表单验证

如果在Form 表单里有通过v-for动态生成&#xff0c;如何设置验证呢&#xff1f; <el-form ref"ruleFormRef" :model"ruleForm" status-icon :rules"rules" label-width"120px"class"demo-ruleForm" hide-required-aster…

大数据课程综合实验案例---课设问题汇总

最近翻看两年前的大数据课设&#xff0c;感觉这个大数据课设实验当时答辩 在大数据课设实验过程中&#xff0c;我遇到了很多问题&#xff0c;在这里做出汇总&#xff1a; 1、MySQL启动报错 首先&#xff0c;我的MySQL有时候启动不了&#xff0c;当我输入这个命令的时候&#…

ModuleNotFoundError: No module named sklearn

前言 出现ModuleNotFoundError: No module named sklearn’的debug过程记录 步骤 安装机器学习库&#xff0c;需要注意报错的sklearn是scikit-learn缩写。 pip install scikit-learn 完成&#xff0c;不再报错

剖析Linuxptp中ptp4l实现--OC

源码克隆地址&#xff1a; git://git.code.sf.net/p/linuxptp/code 项目官网文档&#xff1a; https://linuxptp.nwtime.org/documentation/ 关于linuxptp的相关配置可以参考以下博文&#xff1a; linuxptp/ptp4l PTP时钟同步配置选项 代码剖析 ptp4l的main函数在ptp4l.…

“学习嵌入式开发:明确目标,提升技能“

嵌入式领域涵盖广泛&#xff0c;不可能一次性掌握所有知识。因此&#xff0c;明确学习目标和方向非常重要。选择感兴趣且与职业发展相关的领域进行深入学习是明智之举。 嵌入式技术在不断发展&#xff0c;过去与现在存在差异。选择学习当前行业的主流技术和趋势是明智选择。掌…

基于STM32设计的人体健康监护系统(华为云IOT)

一、设计需求 1.1 设计需求总结 根据需求,要求设计一款基于 STM32 的人体健康监护系统。采用系统模块化思路进行,将多个数模传感器收集到的数据和操作指令一并送至 STM32 中心处理器进行处理分析。 该系统可以实时监测被测者的心率、体温以及周围环境的温度,也同时可以通…

生物信息学_玉泉路_课堂笔记_06 第六章 基因组学:遗传变异分析以及FGWAS

&#x1f345; 课程&#xff1a;生物信息学_玉泉路_课堂笔记 中科院_2022秋季课 第一学期 &#x1f345; 个人笔记使用 &#x1f345; 2023/7/21 课程回顾 第六章 基因组学&#xff1a;遗传变异分析以及FGWAS 第一节 SNP 与 Indel 的鉴定与分析 基本概念 参考基因组 和基因组…

tinkerCAD案例:9.Twist Earrings 扭耳环

tinkerCAD案例&#xff1a;9.Twist Earrings 扭耳环 In this lesson you learn how to create earrings by using cylinder shapes. Let’s get started! 在本课中&#xff0c;您将学习如何使用圆柱形制作耳环。让我们开始吧&#xff01; 说明 Drag a Cylinder shape to the w…

为Android构建现代应用—— 练习状态管理

介绍 本章是一个应用上一章&#xff1a;设计原则中学到的概念的项目。 项目的目标包括以下实现&#xff1a; • 创建一个应用程序&#xff0c;该应用程序使用View作为真实来源。 • 修改应用程序&#xff0c;使其使用ViewModel作为真实来源。 • 将状态和事件进行分组&#x…