《剑指offer》第三章高质量的代码笔记

面试官会根据应聘者写出的代码的规范性来决定是否录用他。
* 代码书写清楚。特别是白纸或白板上书写的时候,速度慢一点没事
* 规范代码布局清晰。缩进清晰
* 规范的代码命名合理。

通常面试官会检查应聘者代码是否完成了基本功能、输入边界值是否能够得到正确的输出、是否对各种不合规范的非法输入做出合理的错误处理
从3方面确保代码的完整性
* 功能测试
* 边界测试
* 负面测试,这个指各种可能的错误的输入

三种错误处理的方法
* 用返回值告知调用者出错
* 当发生错误是设置一个全局变量,容易遗忘检测这个全局变量
* 抛出异常

面试题11:数值的整数次方

题目:实现函数 double Power(double base, int exponent),求base的exponent次方,不得使用库函数。
知识点整理:
* double类型==判断
* 指数为负数,底数为零切指数为负数的倒数
“`java
#我把书中的代码转化成java了
public class Power {
public double getPower(double base, int exponent){

    if(equal(base, 0.0) && exponent < 0){
        System.out.println("base can not be 0.0 and exponent can not be negtive");
        return 0.0;
    }
    int absExponent = exponent;
    if(exponent < 0){
        absExponent = -exponent;
    }

    double result = this.PowerWithUnsignedExponent(base, absExponent);
    if(exponent < 0){
        result = 1.0 / result;
    }

    return result;
}
public double PowerWithUnsignedExponent(double base, int exponent){
    if(exponent == 0)
        return 1;
    if(exponent == 1)
        return base;

    double result = this.PowerWithUnsignedExponent(base, exponent >> 1);
    result *= result;

    if((exponent & 0x1) ==1)
        result *= base;

    return result;
}
Boolean equal(double num1, double num2){
    if((num1 - num2) > -0.000001 && (num1 - num2) < 0.000001){
        return true;
    }
    else{
        return false;
    }
}

}
“`

面试题12:打印1到最大数的n位输

题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1,2,3一直到最大的3位数即999
知识点整理:
* n位数的范围没有规定,需要考虑大数问题
* 使用字符串或数组表达大数
* 如何打印字符串表示的数字,考虑”098”的打印。需要按照我们的阅读吸光打印数字
“`java
public class MaxOfNDigits {
public void PrintToMaxOfNDigits(int n){
if(n <= 0)
return;

    char numbers[] = new char[n + 1];
    numbers[n] = '\0';

    for(int i = 0; i < 10; i++){
        numbers[0] = (char) (i + '0');
        Print1ToMaxOfNDigitsRecursively(numbers, n, 0);
    }
}

void Print1ToMaxOfNDigitsRecursively(char numbers[], int length, int index ){
    if(index == length-1){
        PrintNumbers(numbers, length);
        return;
    }

    for(int i = 0; i < 10; i++){
        numbers[index + 1] =( char)(i + '0');
        this.Print1ToMaxOfNDigitsRecursively(numbers, length, index + 1);
    }

}

void PrintNumbers(char numbers[], int length){
    int beginAt = length - 1;
    for(;beginAt > 0;beginAt--){
        if(numbers[beginAt] != '0')
            break;
    }

    for(;beginAt >= 0; beginAt--){
        System.out.print(numbers[beginAt]);
    }

    System.out.println();;
}

}

```

面试题13:在O(1)时间删除链表节点

题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。
知识点整理:
* 把下一个节点的内容复制到需要删除的节点上覆盖原有的内容,再把下一个节点删除,相当于删除前一个节点
* 考虑一些“如果…那么…”的情况。如果要删除的节点位于链表的尾部,那么没有下一个节点,怎么办?如果链表中只有一个节点,而我们又要删除链表的头结点。
* 书中的算法是基于一个假设,要删除的节点不在链表中呢
PS java中这个链表的实现有点小麻烦,我就没有做了

面试题14:调整数组顺序使奇数位于偶数前面

题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分
知识点整理:
* 考虑扩展性,如果这里的条件换成所有负数都在非负数的前面,或者能被3整除的数都在不能被3整除的数的前面
* 书中的方式是讲这些条件单做一个函数传入,这是使用c++的思路来做的。在java中,可以定义一个接口,或者虚类,来实现这个条件函数。将这个接口或者虚类传入就可以了。下面的代码哦没有实现。

```java
/**
 * 调整数组数学使奇数位于偶数前面
 * @author wq
 *
 */
public class offer14ReorderOddEven {
public int[] getReorderOddEven(int data[]){
    if(data.length == 0 )
        return data;

    int start = 0, end = data.length - 1;
    while(start < end){
        while(start < end && (data[start] & 0x1 ) != 0){
            start++;
        }

        while(start < end &&  (data[end] & 0x1) == 1){
            end--;
        }

        if(start < end){
            int temp = data[start];
            data[start] = data[end];
            data[end] = data[temp];
        }
    }

    return data;
}

}
“`

面试题15:链表中倒数第k个节点

题目:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如一个链表有6个节点,从头节点开始它们的值依次是1,2,3,4,5,6。这个链表的倒数第3个节点是值为4的节点。
知识点总结:
* 思路:定义两个指针,中间间隔k个节点,一起运动,当最后一个节点到达末尾的时候,第一个节点指示的数就是倒数第k个节点。
* 可能会遇到的问题:当输入链表为空指针,链表中节点数量少于k,输入的参数k为0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章