《剑指Offer》记录

2017-04-09  本文已影响73人  codingXue

第1章 面试的流程

  1. 编程时应注意的三点:
  1. 现场面试时,记得准备几个问题。(每轮面试的最后,面试官可能会让面试者问问题)

  2. 项目经验的描述(STAR)

常被问的问题包括:

  1. 面试中应聘者需要具备的素质:
  1. 高质量代码的例子——将字符串转换成整数 int StrToInt(char* string),你是否能考虑到下面几个方面?

第2章 面试的基础知识

  1. 编程语言(如C++)
    面试题1 为CMyString实现赋值运算符。
class CMyString
{
public:
    CMyString(char* pData=NULL);
    CMyString(const CMyString& str);
    ~CMyString(void);
private:
    char* m_pData;
};

考虑因素:

高阶:

  1. 数据结构的例子:向单链表尾部插入一个数据。需要注意的是,由于当输入链表为空时,会修改指向输入链表的指针,因此要将输入指针设为指向指针的指针,否则出了这个函数,它仍是一个空指针。

  2. 算法和数据操作:
    面试题8:旋转数组(例如[3, 4, 5, 1, 2])中的最小值。需要考虑的内容:

面试题9的相关题目:斐波那契的变体
用一个2x1的小矩形去覆盖2xn的大矩形,有多少种方法?本质仍是斐波那契数列。

面试题10:二进制中1的个数。
常规解法:

//与 1、10、100、1000依次相与
int NumberOf1(int n)
{
    int count = 0;
    usigned int flag = 1;
    while(flag)
    {
        if(n & flag)
            count++;
        flag = flag << 1;
    }
    return count;
}

高阶解法:

//n-1会将n的右数第一个1变成0,右边的所有0变成1,so (n-1) & n 抹去了n的右数第一个1
int NumberOf1(int n)
{
    int count = 0;
    while(n)
    {
        ++count;
        n = (n-1) & n;
    }
    return count;
}

第3章 高质量的代码

  1. 面试题13:在O(1)时间删除链表节点
    如果遍历链表找到目标节点的前驱,并进行删除,则需要O(n)的时间,要在O(1)时间内删除节点,采用的方法是将目标节点的后继复制到目标节点,并删除目标节点的后继节点!
    需要注意的内容包括:

第4章 解决面试题的思路

  1. 面试题26:复杂链表的复制
    复杂链表的节点不仅包含一个指向下一个节点的指针pNext,还有一个指向链表中任意节点或者NULL的指针pSibling。

第5章 优化时间和空间效率

  1. 面试题29:数组中出现次数超过一半的数字
  1. 面试题30:最小的k个数
  1. 面试题31:连续子数组最大和
    解法:从头逐个累加,若当前累加结果小于零,则抛弃当前结果,将和置零,从下一个数字开始重新累加。要持续判断当前和是否大于当前最大和。

  2. 面试题32:从1到n整数中1出现的次数
    实例分析:以21345为例,我们把它分成两段,1-1345和1346-21345,第二段是20000个数。我们来看1346-21345。这一段,1出现在首位有10000次(如果首位为1则不足10000次,而是1345+1次)。再看这一段中,1出现在后4位是什么情况,我们进一步把1346-21345分解成1346-11345和11346-21345,即两个10000,那么这4位中,任意一位为1时,其他3位可以任选0-9,因此出现次数为2*103。代码直接贴图了:


    注意,复杂度是O(logn)哦!
  3. 面试题33:把数组排成最小的数
    解法:两个字符串m和n,可以拼成mn也可以拼成nm,于是定义一个比较方法,若mn<nm则m<n,即m应该放在n前面。因此对数组进行排序,然后拼接即可。

  4. 面试题34:丑数
    LeetCode里做过,题解264. Ugly Number II,感觉自己写的代码好优美呢哈哈哈哈哈。

  5. 面试题36:数组中的逆序对
    解法:用归并排序的想法做。假设数组的前面一半和后面一半已经各自排好序,那么合并时候,依次取两个部分尾部较大的数写入新数组,如果取的是前面一半的数,那么当前后面一半还剩的数,都会跟它构成逆序数!

第6章 面试中的各项能力

  1. 知识迁移能力
    面试题39:二叉树的深度

面试题40:数组中只出现一次的数字
一个整形数组中,除了两个数字以外,其他数字都出现了两次,请找出这两个数字。

面试题41:和为s的两个数字 VS 和为s的连续正数序列(都是排序数组)

面试题42:翻转单词顺序 VS 左旋转字符串

  1. 抽象建模能力
    面试题43:n个骰子的点数。
    n个骰子扔地上,s为朝上一面的点数和,求所有s的可能值及其概率。

面试题45:约瑟夫环

  1. 发散思维能力
    这部分题好多是涉及语言特点的,比如C++的类等,我这方面还没有准备,没有学好,先简单记一下,可能语言过关了再回头看会好一些。
    面试题46:求1+2+...+n
    不准用乘除、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)

面试题47:不用加减乘除做加法
用位运算!不考虑进位=a^b,进位=a&b<<1,需要循环进行,直到不产生进位!
相关问题:不用新变量交换两个变量的值。

面试题48:不能被继承的类

第7章 两个面试案例

略,主要还是要把细节考虑到,如参数的检查,边缘条件,错误输入等。

第8章 英文版新增面试题

  1. 面试题51:数组中重复的数字
    一个长度为n的数组里所有数字都在0到n-1之间,某些数字是重复的,但不知道有几个是重复的,请找出任意一个重复数字。
    解法:从头到尾扫描数组,当扫描到下标为i值为m的数字,若m=i,则继续扫描下一个数字,若m≠i,比较它和第m个数字,若相等,则找到了一个重复数字,否则交换m和i位置的数字,即将当前数字归位。

  2. 面试题57:删除链表中重复的节点
    需要注意的是:如果链表的头可能修改,则传入参数的时候不能是ListNode* pHead,而需要是ListNode** pHead!

  3. 面试题64:数据流中的中位数
    解法:我们维护两个堆,一个大顶堆b,一个小顶堆s。我们保证b的最大值比s的最小值要小,那么b里所有值都比s小了,然后让两个堆中元素个数相等,那么通过两个堆的堆顶就能求中位数啦。
    具体可以在数字总数目为偶数时,把数字插入s,数目为奇数时,插入b。但还是要根据数字的大小,维持b的顶比s的顶小。

  4. 面试题65:滑动窗口的最大值
    这题之前根神跟我们说过,确实设计很精巧。

vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
    vector<int> maxInWindows;
    if(num.size() >= size && size >= 1)
    {
        deque<int> index;
        for(unsigned int i = 0; i < size; i++)
        {
            while(!index.empty() && num[i] >= num[index.back()])
                index.pop_back();
            index.push_back(i);
        }
        for(unsigned int i = size; i < num.size(); i++)
        {
            maxInWindows.push_back(num[index.front()]);
            while(!index.empty() && num[i] >= num[index.back()])
                index.pop_back();
            if(!index.empty() && index.front() <= (int)(i - size))
                index.pop_front(i);
        }
        maxInWindows.push_back(num[index.front()]);
    }
    return maxInWindows;
}
上一篇下一篇

猜你喜欢

热点阅读