剑指offer读书笔记:第三章,高质量的代码

问题01 代码的全面性

在写代码的时候要注意各种情况的考虑,一般分为三个方面:

  • 功能测试:这个主要测试可以不可以完成函数的功能,
  • 边界测试:这个尽量要考虑各种极端的case,比如循环条件的边界判断、数据溢出的考虑等等
  • 负面测试:这个主要是各种错误的输入,靠考虑系统的鲁棒性,比如指针为null应该怎么考虑,等等。
  • -

这里写图片描述

问题02 数值的整数次方

这里写图片描述

对于这道题,要考虑四种情况:
1、底数为0,指数为负数的情况,无意义
2、指数为0,返回1
3、指数为负数,返回1.0/base,-exponent
4、指数正数,base,exponent

注意浮点数的等于运算是需要一个评估值

public class Solution {
    public double Power(double base, int exponent) throws Exception{
        double result = 0.0;
        if (equal(base, 0.0) && exponent < 0) {
            throw new Exception("0的负数次幂无意义");

        }
        if (equal(exponent, 0)) {
            return 1.0;
        }
        if (exponent < 0) {
            result = powerWithExponent(1.0 / base, -exponent);
        } else {
            result = powerWithExponent(base, exponent);
        }
        return result;
  }
    private double powerWithExponent(double base, int exponent) {
        double result = 1.0;
        for (int i = 1; i <= exponent; i++) {
            result = result * base;
        }
        return result;
    }
    // 判断两个double型数据,计算机有误差
    private boolean equal(double num1, double num2) {
        if ((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001)) {
            return true;
        } else {
            return false;
        }
    }
}

进一步的优化,直接递归去做

private double powerWithExponent2(double base,int exponent){
        if(exponent == 0){
            return 1;
        }
        if(exponent == 1){
            return base;
        }
        double result = powerWithExponent2(base, exponent >> 1);
        result *= result;
        if((exponent&0x1) == 1){
            result *= base;
        }
        return result;
    }

问题03 打印1到最大的n位数

这里写图片描述

最简单的想法就是先找出最大的n位数,然后循环打印即可。然而上述程序在n很大时,显然会有溢出,int 的范围不够。那么我们会想到用long来存储,但是如果n的值还是很大,以至于long也无法满足要求。那么该怎么办?最好想问一下n的范围:假如在整数范围之内,可以考虑int,否者考虑字符串加法来做。

问题04 在O(1)时间删除链表结点

这里写图片描述

在单向链表中删除一个节点,通常的做法是从链表头开始遍历,如果某个节点的next等于要删除的节点,就将该next改为待删除节点的下一个节点,然后删除该链表节点即可。

因为我们要删除某个节点,如果不是第一个节点的话,就需要更改它前面节点的next值。而单链表是无法逆行的,所以我们可以按如下步骤做:
1. 如果待删除节点不是最后一个节点,就用他的next节点的value覆盖它的value,然后删掉它的next节点。
2. 如果是最后一个节点,还是老老实实的顺序遍历吧。

问题05 调整数组顺序使奇数位于偶数前面

这里写图片描述

首先,说一种时间复杂度为O(n),但是空间复杂度较高的。但是这种代码,肯定不会是面试官喜欢的。我们申请另外两个数组,每次输入数据时,直接比对是奇数还是偶数,顺序存放在两个数组中,并记录下标的变化。最后两个数组顺序输出就行了,
 另一种思想,不开辟新的空间,直接在原始数组上,进行移动。但是考虑到前后的顺序不能变化,因此简单的哨兵替换思想就不可以了。这时候我们可以通过两个下标,进行数据元素的移动。

问题06 链表中倒数第K个结点

这里写图片描述

这个很简单,直接固定窗口即可

问题07 反转链表

这里写图片描述

头部插入法反转链表

注意node为null、node->next为null的情况考虑

问题08 合并两个有序链表

这里写图片描述

直接归并即可,主语链表头结点为null的考虑

问题09 树的子结构

这里写图片描述

双函数DFS深度优先遍历即可

总结

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值