[剑指Offer] 第2章课后题详解

简介: [剑指Offer] 第2章课后题详解目录剑指Offer 第2章课后题详解目录有序数组的插入分析正常解法非主流解法两个队列实现栈分析解法2的整数次方分析解法不同位数分析解法有序数组的插入本题为《剑指Offer》“面试题4:替换空格”一节中的“相关题目”。有两个排序的数组A1和A2,

[剑指Offer] 第2章课后题详解

目录

有序数组的插入

本题为《剑指Offer》“面试题4:替换空格”一节中的“相关题目”。

有两个排序的数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2。请实现一个函数,把A2中的所有数字插入到A1中并且所有数字是排序的。

分析

其实这道题就是实现一个归并排序,只是在数组中,数据是顺序存储的,如果在数组头部进行归并排序,每一次操作都会移动后面所有的数据,开销很大。所以应该从尾部进行操作。

正常解法

//两个数组的初始实际长度是固定,而数组a2也不需要进行改动,所以都可以声明为常量,进行保护。题目中已经说明空间足够,不然还需要再声明一个参数length,表示a1的维度,与a1,a2的初始长度之和进行比较,以防越界。
auto insertArray(int *a1, const int length1, const int *a2, const int length2) -> void{

    //i,j为a1,a2数组实际末尾下标,k为a1数组中进行归并位置的下标
    int i = length1 - 1, j = length2 - 1, k = length1 + length2 - 1;
    while(i >= 0 && j >= 0){
        //如果a1数组中未处理末尾的数大于或等于a2数组中未处理末尾的数,则将a1的该位置的数插入到a1数组末尾,否则插入a2该位置的数
        if(a1[i] >= a2[j]){
            a1[k--] = a1[i--];
        }
        else{
            a1[k--] = a2[j--];
        }
    }
    //如果数组a2中还有元素没有插入到数组a1中,则全部依次插入到数组a1前面位置
    while(j >= 0){
        a1[k--] = a2[j--];
    }
}

非主流解法

使用标准库中的vector(可变大小数组)和泛型算法会让代码变得相当简单,但相应地算法的时间复杂度会受到影响(因为会进行一次排序)。

//传入两个vector的引用
auto inserVector(vector<int> &a1, vector<int> &a2) -> void{
    //将a2的全部元素插入到a1的尾部
    a1.insert(a1.end(), a2.begin(), a2.end());
    //用泛型算法sort函数对a1进行排序
    sort(a1.begin(),a1.end());
}

两个队列实现栈

本题为《剑指Offer》“面试题7:用两个栈实现队列”一节中的“相关题目”。

栈声明如下:

template <typename T> class CStack{
public:
    void push(const T& node);
    T pop();
private:
    queue<T> queue1;
    queue<T> queue2;
    //标志目前元素存储在哪个队列中,1表示queue1,0表示queue2;
    bool flag = 1;
};

分析

根据队列的先进先出原则和栈的后进先出原则,可以进行如下设计:先将入栈元素依次加入到队列1中,出栈时,将队列1除队尾元素外依次加入到队列2中,再弹出队列1中的最后一个元素(队尾元素)。再有元素入栈时,就加入到队列2中,出栈时,将队列2除队尾元素外依次加入到队列1中,再弹出队列2中的最后一个元素(队尾元素)。之后元素入栈,又加入到队列1中,依此类推。

解法

template <typename T> void CStack<T>::push(const T& node){
    if (flag) {
        queue1.push(node);
    }
    else{
        queue2.push(node);
    }
}

template <typename T> T CStack<T>::pop(){
    if (flag) {
        //标志为1,队列1为空时,栈为空
        if (queue1.empty()) {
            throw new runtime_error("stack is empty");
        }
        //将队列1除队尾元素外依次加入到队列2中
        while (queue1.size() > 1) {
            T& data = queue1.front();
            queue1.pop();
            queue2.push(data);
        }
        //修改标志
        flag = 0;
        //弹出并返回队尾元素
        T head = queue1.front();
        queue1.pop();
        return head;
    }
    else{
        //标志为0,队列2为空时,栈为空
        if (queue2.empty()) {
            throw new runtime_error("stack is empty");
        }
        while (queue2.size() > 1) {
            T& data = queue2.front();
            queue2.pop();
            queue1.push(data);
        }
        flag = 1;

        T head = queue2.front();
        queue2.pop();

        return head;
    }
}

2的整数次方

本题为《剑指Offer》“面试题10:二进制中1的个数”一节中的“相关题目”。

用一条语句判断一个整数是不是2的整数次方。

分析

一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0。把这个数减去1之后,原本为1的那一位会变成0,而在这一位之后的所有0都会变成1。把这个整数与它减一后的数做与运算则结果为0。

解法

auto isCubeOf2(const int n) -> bool{
    return !(n & (n - 1));
}

不同位数

本题为《剑指Offer》“面试题10:二进制中1的个数”一节中的“相关题目”。

输入两个整数m和n,计算需要改变m的二进制中多少位才能得到n。

分析

问题等价于m和n中有多少位不同,所以将m和n进行异或运算再计算结果二进制中的1的个数就完成求解。

解法

auto differentNumber(const int m, const int n) -> int{
    //tmp为m和n的异或结果
    int tmp = m ^ n;
    int count = 0;
    unsigned flag = 1;

    //依次检查tmp每一位是否为1
    while(flag){
        if(flag & tmp){
            ++count;
        }
        flag = flag << 1;
    }
    return count;
}
目录
相关文章
|
4月前
|
C语言
蓝桥杯练习题
蓝桥杯练习题包括6道C语言编程题:1. 判断三位数是否为水仙花数;2. 输出区间质因数分解;3. 将秒转换为&#39;H:M:S&#39;格式;4. 判断闰年;5. 删除可被整除元素并排序数组,数字转字母;6. 分类比较两个字符串关系。每题涉及不同逻辑操作,适合编程初学者练习。
33 3
|
算法
牛客网《剑指offer》专栏刷题练习之双指针算法的使用
牛客网《剑指offer》专栏刷题练习之双指针算法的使用
93 0
|
C语言
【leetcode】学了栈和队列却觉得无用武之地?试试这几道题目吧!
【leetcode】学了栈和队列却觉得无用武之地?试试这几道题目吧!
83 0
|
算法 程序员 C++
LeetCode精讲(1)—— 单调栈有关习题及其变式
我们首先是要去熟悉单调栈这种结构,熟悉后,我们遇到问题的时候就只需要将原来包装的问题拆分,层层拆分后发现有用单调栈的这种需求,便可以瞬间联想到并去使用。
238 1
LeetCode精讲(1)—— 单调栈有关习题及其变式
|
算法
代码随想录算法训练营第四天 | 链表 + 每日一题
代码随想录算法训练营第四天 | 链表 + 每日一题
103 0
C语言知识-学习练习题系列-10-4题型
C语言知识-学习练习题系列-10-4题型
C语言知识-学习练习题系列-9-4题型
C语言知识-学习练习题系列-9-4题型
|
人工智能 C语言
C语言知识-学习练习题系列-8-4题型
C语言知识-学习练习题系列-8 4题型
|
算法
做题
学习编程语言的过程要记得刷题哦
92 0
做题
|
存储 算法 Java