剑指Offer学习

目录:

1、【剑指Offer学习】【面试题01:实现赋值运算符函数】

2、【剑指Offer学习】【面试题02:实现Singleton 模式——七种实现方式】

3、【剑指Offer学习】【面试题03:二维数组中的查找】

4、【剑指Offer学习】【面试题04:替换空格】

5、【剑指Offer学习】【面试题05:从尾到头打印链表】

6、【剑指Offer学习】【面试题06:重建二叉树】
7、【剑指Offer学习】【面试题07:用两个栈实现队列】

8、【剑指Offer学习】【面试题08:旋转数组的最小数字】

9、【剑指Offer学习】【面试题09:斐波那契数列】

10、【剑指Offer学习】【面试题10:二进制中1 的个数】

1、【剑指Offer学习】【面试题01:实现赋值运算符函数】

    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    // 面试题1:赋值运算符函数
    // 题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
    
    #include<cstring>
    #include<cstdio>
    
    class CMyString
    {
    public:
        CMyString(char* pData = nullptr);
        CMyString(const CMyString& str);
        ~CMyString(void);
    
        CMyString& operator = (const CMyString& str);
    
        void Print();
          
    private:
        char* m_pData;
    };
    
    CMyString::CMyString(char *pData)
    {
        if(pData == nullptr)
        {
            m_pData = new char[1];
            m_pData[0] = '\0';
        }
        else
        {
            int length = strlen(pData);
            m_pData = new char[length + 1];
            strcpy(m_pData, pData);
        }
    }
    
    CMyString::CMyString(const CMyString &str)
    {
        int length = strlen(str.m_pData);
        m_pData = new char[length + 1];
        strcpy(m_pData, str.m_pData);
    }
    
    CMyString::~CMyString()
    {
        delete[] m_pData;
    }
    
    CMyString& CMyString::operator = (const CMyString& str)
    {
        if(this == &str)
            return *this;
    
        delete []m_pData;
        m_pData = nullptr;
    
        m_pData = new char[strlen(str.m_pData) + 1];
        strcpy(m_pData, str.m_pData);
    
        return *this;
    }
    
    // ====================测试代码====================
    void CMyString::Print()
    {
        printf("%s", m_pData);
    }
    
    void Test1()
    {
        printf("Test1 begins:\n");
    
        char* text = "Hello world";
    
        CMyString str1(text);
        CMyString str2;
        str2 = str1;
    
        printf("The expected result is: %s.\n", text);
    
        printf("The actual result is: ");
        str2.Print();
        printf(".\n");
    }
    
    // 赋值给自己
    void Test2()
    {
        printf("Test2 begins:\n");
    
        char* text = "Hello world";
    
        CMyString str1(text);
        str1 = str1;
    
        printf("The expected result is: %s.\n", text);
    
        printf("The actual result is: ");
        str1.Print();
        printf(".\n");
    }
    
    // 连续赋值
    void Test3()
    {
        printf("Test3 begins:\n");
    
        char* text = "Hello world";
    
        CMyString str1(text);
        CMyString str2, str3;
        str3 = str2 = str1;
    
        printf("The expected result is: %s.\n", text);
    
        printf("The actual result is: ");
        str2.Print();
        printf(".\n");
    
        printf("The expected result is: %s.\n", text);
    
        printf("The actual result is: ");
        str3.Print();
        printf(".\n");
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
    
        return 0;
    }

2、【剑指Offer学习】【面试题02:实现Singleton 模式——七种实现方式】

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.
    
    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/
    
    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    // 面试题2:实现Singleton模式
    // 题目:设计一个类,我们只能生成该类的一个实例。
    
    using System;
    
    namespace _02_Singleton
    {
        public sealed class Singleton1
        {
            private Singleton1()
            {
            }
    
            private static Singleton1 instance = null;
            public static Singleton1 Instance
            {
                get
                {
                    if (instance == null)
                        instance = new Singleton1();
    
                    return instance;
                }
            }
        }
    
        public sealed class Singleton2
        {
            private Singleton2()
            {
            }
    
            private static readonly object syncObj = new object();
    
            private static Singleton2 instance = null;
            public static Singleton2 Instance
            {
                get
                {
                    lock (syncObj)
                    {
                        if (instance == null)
                            instance = new Singleton2();
                    }
    
                    return instance;
                }
            }
        }
    
        public sealed class Singleton3
        {
            private Singleton3()
            {
            }
    
            private static object syncObj = new object();
    
            private static Singleton3 instance = null;
            public static Singleton3 Instance
            {
                get
                {
                    if (instance == null)
                    {
                        lock (syncObj)
                        {
                            if (instance == null)
                                instance = new Singleton3();
                        }
                    }
    
                    return instance;
                }
            }
        }
    
        public sealed class Singleton4
        {
            private Singleton4()
            {
                Console.WriteLine("An instance of Singleton4 is created.");
            }
    
            public static void Print()
            {
                Console.WriteLine("Singleton4 Print");
            }
    
            private static Singleton4 instance = new Singleton4();
            public static Singleton4 Instance
            {
                get
                {
                    return instance;
                }
            }
        }
    
        public sealed class Singleton5
        {
            Singleton5()
            {
                Console.WriteLine("An instance of Singleton5 is created.");
            }
    
            public static void Print()
            {
                Console.WriteLine("Singleton5 Print");
            }
    
            public static Singleton5 Instance
            {
                get
                {
                    return Nested.instance;
                }
            }
    
            class Nested
            {
                static Nested()
                {
                }
    
                internal static readonly Singleton5 instance = new Singleton5();
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                // 也会打印An instance of Singleton4 is created.
                Singleton4.Print();
    
                // 不会打印An instance of Singleton5 is created.
                Singleton5.Print();
            }
        }
    }

3、【剑指Offer学习】【面试题03:二维数组中的查找】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.
        
        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/
        
        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================
        
        // 面试题3(一):找出数组中重复的数字
        // 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,
        // 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, 5, 3},
        // 那么对应的输出是重复的数字2或者3。
        
        #include <cstdio>
        
        // 参数:
        //        numbers:     一个整数数组
        //        length:      数组的长度
        //        duplication: (输出) 数组中的一个重复的数字
        // 返回值:             
        //        true  - 输入有效,并且数组中存在重复的数字
        //        false - 输入无效,或者数组中没有重复的数字
        bool duplicate(int numbers[], int length, int* duplication)
        {
            if(numbers == nullptr || length <= 0)
                return false;
        
            for(int i = 0; i < length; ++i)
            {
                if(numbers[i] < 0 || numbers[i] > length - 1)
                    return false;
            }
        
            for(int i = 0; i < length; ++i)
            {
                while(numbers[i] != i)
                {
                    if(numbers[i] == numbers[numbers[i]])
                    {
                        *duplication = numbers[i];
                        return true;
                    }
        
                    // 交换numbers[i]和numbers[numbers[i]]             
                    int temp = numbers[i];
                    numbers[i] = numbers[temp];
                    numbers[temp] = temp;
                }
            }
        
            return false;
        }
        
        // ====================测试代码====================
        bool contains(int array[], int length, int number)
        {
            for(int i = 0; i < length; ++i)
            {
                if(array[i] == number)
                    return true;
            }
        
            return false;
        }
        
        void test(char* testName, int numbers[], int lengthNumbers, int expected[], int expectedExpected, bool validArgument)
        {
            printf("%s begins: ", testName);
        
            int duplication;
            bool validInput = duplicate(numbers, lengthNumbers, &duplication);
        
            if(validArgument == validInput)
            {
                if(validArgument)
                {
                    if(contains(expected, expectedExpected, duplication))
                        printf("Passed.\n");
                    else
                        printf("FAILED.\n");
                }
                else
                    printf("Passed.\n");
            }
            else
                printf("FAILED.\n");
        }
        
        // 重复的数字是数组中最小的数字
        void test1()
        {
            int numbers[] = { 2, 1, 3, 1, 4 };
            int duplications[] = { 1 };
            test("Test1", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
        }
        
        // 重复的数字是数组中最大的数字
        void test2()
        {
            int numbers[] = { 2, 4, 3, 1, 4 };
            int duplications[] = { 4 };
            test("Test2", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
        }
        
        // 数组中存在多个重复的数字
        void test3()
        {
            int numbers[] = { 2, 4, 2, 1, 4 };
            int duplications[] = { 2, 4 };
            test("Test3", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
        }
        
        // 没有重复的数字
        void test4()
        {
            int numbers[] = { 2, 1, 3, 0, 4 };
            int duplications[] = { -1 }; // not in use in the test function
            test("Test4", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
        }
        
        // 没有重复的数字
        void test5()
        {
            int numbers[] = { 2, 1, 3, 5, 4 };
            int duplications[] = { -1 }; // not in use in the test function
            test("Test5", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
        }
        
        // 无效的输入
        void test6()
        {
            int* numbers = nullptr;
            int duplications[] = { -1 }; // not in use in the test function
            test("Test6", numbers, 0, duplications, sizeof(duplications) / sizeof(int), false);
        }
        
        void main()
        {
            test1();
            test2();
            test3();
            test4();
            test5();
            test6();
            while(1);
        }

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.
    
    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/
    
    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    // 面试题3(二):不修改数组找出重复的数字
    // 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至
    // 少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的
    // 数组。例如,如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的
    // 输出是重复的数字2或者3。
    
    #include <iostream>
    
    int countRange(const int* numbers, int length, int start, int end);
    
    // 参数:
    //        numbers:     一个整数数组
    //        length:      数组的长度
    // 返回值:             
    //        正数  - 输入有效,并且数组中存在重复的数字,返回值为重复的数字
    //        负数  - 输入无效,或者数组中没有重复的数字
    int getDuplication(const int* numbers, int length)
    {
        if(numbers == nullptr || length <= 0)
            return -1;
    
        int start = 1;
        int end = length - 1;
        while(end >= start)
        {
            int middle = ((end - start) >> 1) + start;
            int count = countRange(numbers, length, start, middle);
            if(end == start)
            {
                if(count > 1)
                    return start;
                else
                    break;
            }
    
            if(count > (middle - start + 1))
                end = middle;
            else
                start = middle + 1;
        }
        return -1;
    }
    
    int countRange(const int* numbers, int length, int start, int end)
    {
        if(numbers == nullptr)
            return 0;
    
        int count = 0;
        for(int i = 0; i < length; i++)
            if(numbers[i] >= start && numbers[i] <= end)
                ++count;
        return count;
    }
    
    // ====================测试代码====================
    void test(const char* testName, int* numbers, int length, int* duplications, int dupLength)
    {
        int result = getDuplication(numbers, length);
        for(int i = 0; i < dupLength; ++i)
        {
            if(result == duplications[i])
            {
                std::cout << testName << " passed." << std::endl;
                return;
            }
        }
        std::cout << testName << " FAILED." << std::endl;
    }
    
    // 多个重复的数字
    void test1()
    {
        int numbers[] = { 2, 3, 5, 4, 3, 2, 6, 7 };
        int duplications[] = { 2, 3 };
        test("test1", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 一个重复的数字
    void test2()
    {
        int numbers[] = { 3, 2, 1, 4, 4, 5, 6, 7 };
        int duplications[] = { 4 };
        test("test2", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 重复的数字是数组中最小的数字
    void test3()
    {
        int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 1, 8 };
        int duplications[] = { 1 };
        test("test3", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 重复的数字是数组中最大的数字
    void test4()
    {
        int numbers[] = { 1, 7, 3, 4, 5, 6, 8, 2, 8 };
        int duplications[] = { 8 };
        test("test4", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 数组中只有两个数字
    void test5()
    {
        int numbers[] = { 1, 1 };
        int duplications[] = { 1 };
        test("test5", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 重复的数字位于数组当中
    void test6()
    {
        int numbers[] = { 3, 2, 1, 3, 4, 5, 6, 7 };
        int duplications[] = { 3 };
        test("test6", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 多个重复的数字
    void test7()
    {
        int numbers[] = { 1, 2, 2, 6, 4, 5, 6 };
        int duplications[] = { 2, 6 };
        test("test7", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 一个数字重复三次
    void test8()
    {
        int numbers[] = { 1, 2, 2, 6, 4, 5, 2 };
        int duplications[] = { 2 };
        test("test8", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 没有重复的数字
    void test9()
    {
        int numbers[] = { 1, 2, 6, 4, 5, 3 };
        int duplications[] = { -1 };
        test("test9", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int));
    }
    
    // 无效的输入
    void test10()
    {
        int* numbers = nullptr;
        int duplications[] = { -1 };
        test("test10", numbers, 0, duplications, sizeof(duplications) / sizeof(int));
    }
    
    void main()
    {
        test1();
        test2();
        test3();
        test4();
        test5();
        test6();
        test7();
        test8();
        test9();
        test10();
    }

4、【剑指Offer学习】【面试题04:替换空格】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.
        
        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/
        
        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================
        
        // 面试题4:二维数组中的查找
        // 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按
        // 照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个
        // 整数,判断数组中是否含有该整数。
        
        #include <cstdio>
        
        bool Find(int* matrix, int rows, int columns, int number)
        {
            bool found = false;
        
            if(matrix != nullptr && rows > 0 && columns > 0)
            {
                int row = 0;
                int column = columns - 1;
                while(row < rows && column >=0)
                {
                    if(matrix[row * columns + column] == number)
                    {
                        found = true;
                        break;
                    }
                    else if(matrix[row * columns + column] > number)
                        -- column;
                    else
                        ++ row;
                }
            }
        
            return found;
        }
        
        // ====================测试代码====================
        void Test(char* testName, int* matrix, int rows, int columns, int number, bool expected)
        {
            if(testName != nullptr)
                printf("%s begins: ", testName);
        
            bool result = Find(matrix, rows, columns, number);
            if(result == expected)
                printf("Passed.\n");
            else
                printf("Failed.\n");
        }
        
        //  1   2   8   9
        //  2   4   9   12
        //  4   7   10  13
        //  6   8   11  15
        // 要查找的数在数组中
        void Test1()
        {
            int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
            Test("Test1", (int*)matrix, 4, 4, 7, true);
        }
        
        //  1   2   8   9
        //  2   4   9   12
        //  4   7   10  13
        //  6   8   11  15
        // 要查找的数不在数组中
        void Test2()
        {
            int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
            Test("Test2", (int*)matrix, 4, 4, 5, false);
        }
        
        //  1   2   8   9
        //  2   4   9   12
        //  4   7   10  13
        //  6   8   11  15
        // 要查找的数是数组中最小的数字
        void Test3()
        {
            int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
            Test("Test3", (int*)matrix, 4, 4, 1, true);
        }
        
        //  1   2   8   9
        //  2   4   9   12
        //  4   7   10  13
        //  6   8   11  15
        // 要查找的数是数组中最大的数字
        void Test4()
        {
            int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
            Test("Test4", (int*)matrix, 4, 4, 15, true);
        }
        
        //  1   2   8   9
        //  2   4   9   12
        //  4   7   10  13
        //  6   8   11  15
        // 要查找的数比数组中最小的数字还小
        void Test5()
        {
            int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
            Test("Test5", (int*)matrix, 4, 4, 0, false);
        }
        
        //  1   2   8   9
        //  2   4   9   12
        //  4   7   10  13
        //  6   8   11  15
        // 要查找的数比数组中最大的数字还大
        void Test6()
        {
            int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
            Test("Test6", (int*)matrix, 4, 4, 16, false);
        }
        
        // 鲁棒性测试,输入空指针
        void Test7()
        {
            Test("Test7", nullptr, 0, 0, 16, false);
        }
        
        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();
            Test4();
            Test5();
            Test6();
            Test7();
        
            return 0;
        }
        

5、【剑指Offer学习】【面试题05:从尾到头打印链表】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.
        
        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/
        
        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================
        
        // 面试题5:替换空格
        // 题目:请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入“We are happy.”,
        // 则输出“We%20are%20happy.”。
        
        #include <cstdio>
        #include <cstring>
        
        /*length 为字符数组str的总容量,大于或等于字符串str的实际长度*/
        void ReplaceBlank(char str[], int length)
        {
            if(str == nullptr && length <= 0)
                return;
        
            /*originalLength 为字符串str的实际长度*/
            int originalLength = 0;
            int numberOfBlank = 0;
            int i = 0;
            while(str[i] != '\0')
            {
                ++ originalLength;
        
                if(str[i] == ' ')
                    ++ numberOfBlank;
        
                ++ i;
            }
        
            /*newLength 为把空格替换成'%20'之后的长度*/
            int newLength = originalLength + numberOfBlank * 2;
            if(newLength > length)
                return;
        
            int indexOfOriginal = originalLength;
            int indexOfNew = newLength;
            while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
            {
                if(str[indexOfOriginal] == ' ')
                {
                    str[indexOfNew --] = '0';
                    str[indexOfNew --] = '2';
                    str[indexOfNew --] = '%';
                }
                else
                {
                    str[indexOfNew --] = str[indexOfOriginal];
                }
        
                -- indexOfOriginal;
            }
        }
        
        // ====================测试代码====================
        void Test(char* testName, char str[], int length, char expected[])
        {
            if(testName != nullptr)
                printf("%s begins: ", testName);
        
            ReplaceBlank(str, length);
        
            if(expected == nullptr && str == nullptr)
                printf("passed.\n");
            else if(expected == nullptr && str != nullptr)
                printf("failed.\n");
            else if(strcmp(str, expected) == 0)
                printf("passed.\n");
            else
                printf("failed.\n");
        }
        
        // 空格在句子中间
        void Test1()
        {
            const int length = 100;
        
            char str[length] = "hello world";
            Test("Test1", str, length, "hello%20world");
        }
        
        // 空格在句子开头
        void Test2()
        {
            const int length = 100;
        
            char str[length] = " helloworld";
            Test("Test2", str, length, "%20helloworld");
        }
        
        // 空格在句子末尾
        void Test3()
        {
            const int length = 100;
        
            char str[length] = "helloworld ";
            Test("Test3", str, length, "helloworld%20");
        }
        
        // 连续有两个空格
        void Test4()
        {
            const int length = 100;
        
            char str[length] = "hello  world";
            Test("Test4", str, length, "hello%20%20world");
        }
        
        // 传入nullptr
        void Test5()
        {
            Test("Test5", nullptr, 0, nullptr);
        }
        
        // 传入内容为空的字符串
        void Test6()
        {
            const int length = 100;
        
            char str[length] = "";
            Test("Test6", str, length, "");
        }
        
        //传入内容为一个空格的字符串
        void Test7()
        {
            const int length = 100;
        
            char str[length] = " ";
            Test("Test7", str, length, "%20");
        }
        
        // 传入的字符串没有空格
        void Test8()
        {
            const int length = 100;
        
            char str[length] = "helloworld";
            Test("Test8", str, length, "helloworld");
        }
        
        // 传入的字符串全是空格
        void Test9()
        {
            const int length = 100;
        
            char str[length] = "   ";
            Test("Test9", str, length, "%20%20%20");
        }
        
        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();
            Test4();
            Test5();
            Test6();
            Test7();
            Test8();
            Test9();
        
            return 0;
        }
        

6、【剑指Offer学习】【面试题06:重建二叉树】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.
        
        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/
        
        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================
        
        // 面试题6:从尾到头打印链表
        // 题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
        
        #include "..\Utilities\List.h"
        #include <stack>
        
        void PrintListReversingly_Iteratively(ListNode* pHead)
        {
            std::stack<ListNode*> nodes;
        
            ListNode* pNode = pHead;
            while(pNode != nullptr)
            {
                nodes.push(pNode);
                pNode = pNode->m_pNext;
            }
        
            while(!nodes.empty())
            {
                pNode = nodes.top();
                printf("%d\t", pNode->m_nValue);
                nodes.pop();
            }
        }
        
        void PrintListReversingly_Recursively(ListNode* pHead)
        {
            if(pHead != nullptr)
            {
                if (pHead->m_pNext != nullptr)
                {
                    PrintListReversingly_Recursively(pHead->m_pNext);
                }
         
                printf("%d\t", pHead->m_nValue);
            }
        }
        
        // ====================测试代码====================
        void Test(ListNode* pHead)
        {
            PrintList(pHead);
            PrintListReversingly_Iteratively(pHead);
            printf("\n");
            PrintListReversingly_Recursively(pHead);
        }
        
        // 1->2->3->4->5
        void Test1()
        {
            printf("\nTest1 begins.\n");
        
            ListNode* pNode1 = CreateListNode(1);
            ListNode* pNode2 = CreateListNode(2);
            ListNode* pNode3 = CreateListNode(3);
            ListNode* pNode4 = CreateListNode(4);
            ListNode* pNode5 = CreateListNode(5);
        
            ConnectListNodes(pNode1, pNode2);
            ConnectListNodes(pNode2, pNode3);
            ConnectListNodes(pNode3, pNode4);
            ConnectListNodes(pNode4, pNode5);
        
            Test(pNode1);
        
            DestroyList(pNode1);
        }
        
        // 只有一个结点的链表: 1
        void Test2()
        {
            printf("\nTest2 begins.\n");
        
            ListNode* pNode1 = CreateListNode(1);
        
            Test(pNode1);
        
            DestroyList(pNode1);
        }
        
        // 空链表
        void Test3()
        {
            printf("\nTest3 begins.\n");
        
            Test(nullptr);
        }
        
        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();
        
            return 0;
        }
        

7、【剑指Offer学习】【面试题07:用两个栈实现队列】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.
        
        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/
        
        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================
        
        // 面试题7:重建二叉树
        // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输
        // 入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,
        // 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出
        // 图2.6所示的二叉树并输出它的头结点。
        
        #include "..\Utilities\BinaryTree.h"
        #include <exception>
        #include <cstdio>
        
        BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);
        
        BinaryTreeNode* Construct(int* preorder, int* inorder, int length)
        {
            if(preorder == nullptr || inorder == nullptr || length <= 0)
                return nullptr;
        
            return ConstructCore(preorder, preorder + length - 1,
                inorder, inorder + length - 1);
        }
        
        BinaryTreeNode* ConstructCore
        (
            int* startPreorder, int* endPreorder, 
            int* startInorder, int* endInorder
        )
        {
            // 前序遍历序列的第一个数字是根结点的值
            int rootValue = startPreorder[0];
            BinaryTreeNode* root = new BinaryTreeNode();
            root->m_nValue = rootValue;
            root->m_pLeft = root->m_pRight = nullptr;
        
            if(startPreorder == endPreorder)
            {
                if(startInorder == endInorder && *startPreorder == *startInorder)
                    return root;
                else
                    throw std::exception("Invalid input.");
            }
        
            // 在中序遍历中找到根结点的值
            int* rootInorder = startInorder;
            while(rootInorder <= endInorder && *rootInorder != rootValue)
                ++ rootInorder;
        
            if(rootInorder == endInorder && *rootInorder != rootValue)
                throw std::exception("Invalid input.");
        
            int leftLength = rootInorder - startInorder;
            int* leftPreorderEnd = startPreorder + leftLength;
            if(leftLength > 0)
            {
                // 构建左子树
                root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, 
                    startInorder, rootInorder - 1);
            }
            if(leftLength < endPreorder - startPreorder)
            {
                // 构建右子树
                root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
                    rootInorder + 1, endInorder);
            }
        
            return root;
        }
        
        // ====================测试代码====================
        void Test(char* testName, int* preorder, int* inorder, int length)
        {
            if(testName != nullptr)
                printf("%s begins:\n", testName);
        
            printf("The preorder sequence is: ");
            for(int i = 0; i < length; ++ i)
                printf("%d ", preorder[i]);
            printf("\n");
        
            printf("The inorder sequence is: ");
            for(int i = 0; i < length; ++ i)
                printf("%d ", inorder[i]);
            printf("\n");
        
            try
            {
                BinaryTreeNode* root = Construct(preorder, inorder, length);
                PrintTree(root);
        
                DestroyTree(root);
            }
            catch(std::exception& exception)
            {
                printf("Invalid Input.\n");
            }
        }
        
        // 普通二叉树
        //              1
        //           /     \
        //          2       3  
        //         /       / \
        //        4       5   6
        //         \         /
        //          7       8
        void Test1()
        {
            const int length = 8;
            int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};
            int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};
        
            Test("Test1", preorder, inorder, length);
        }
        
        // 所有结点都没有右子结点
        //            1
        //           / 
        //          2   
        //         / 
        //        3 
        //       /
        //      4
        //     /
        //    5
        void Test2()
        {
            const int length = 5;
            int preorder[length] = {1, 2, 3, 4, 5};
            int inorder[length] = {5, 4, 3, 2, 1};
        
            Test("Test2", preorder, inorder, length);
        }
        
        // 所有结点都没有左子结点
        //            1
        //             \ 
        //              2   
        //               \ 
        //                3 
        //                 \
        //                  4
        //                   \
        //                    5
        void Test3()
        {
            const int length = 5;
            int preorder[length] = {1, 2, 3, 4, 5};
            int inorder[length] = {1, 2, 3, 4, 5};
        
            Test("Test3", preorder, inorder, length);
        }
        
        // 树中只有一个结点
        void Test4()
        {
            const int length = 1;
            int preorder[length] = {1};
            int inorder[length] = {1};
        
            Test("Test4", preorder, inorder, length);
        }
        
        // 完全二叉树
        //              1
        //           /     \
        //          2       3  
        //         / \     / \
        //        4   5   6   7
        void Test5()
        {
            const int length = 7;
            int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
            int inorder[length] = {4, 2, 5, 1, 6, 3, 7};
        
            Test("Test5", preorder, inorder, length);
        }
        
        // 输入空指针
        void Test6()
        {
            Test("Test6", nullptr, nullptr, 0);
        }
        
        // 输入的两个序列不匹配
        void Test7()
        {
            const int length = 7;
            int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
            int inorder[length] = {4, 2, 8, 1, 6, 3, 7};
        
            Test("Test7: for unmatched input", preorder, inorder, length);
        }
        
        int main(int argc, char* argv[])
        {
            Test1();
            Test2();
            Test3();
            Test4();
            Test5();
            Test6();
            Test7();
        
            return 0;
        }
        

8、【剑指Offer学习】【面试题08:旋转数组的最小数字】

        /*******************************************************************
        Copyright(c) 2016, Harry He
        All rights reserved.
        
        Distributed under the BSD license.
        (See accompanying file LICENSE.txt at
        https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
        *******************************************************************/
        
        //==================================================================
        // 《剑指Offer——名企面试官精讲典型编程题》代码
        // 作者:何海涛
        //==================================================================
        
        // 面试题8:二叉树的下一个结点
        // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?
        // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针。
        
        #include <stdio.h>
        
        struct BinaryTreeNode
        {
            int                    m_nValue;
            BinaryTreeNode*        m_pLeft;
            BinaryTreeNode*        m_pRight;
            BinaryTreeNode*        m_pParent;
        };
        
        BinaryTreeNode* GetNext(BinaryTreeNode* pNode)
        {
            if(pNode == nullptr)
                return nullptr;
        
            BinaryTreeNode* pNext = nullptr;
            if(pNode->m_pRight != nullptr)
            {
                BinaryTreeNode* pRight = pNode->m_pRight;
                while(pRight->m_pLeft != nullptr)
                    pRight = pRight->m_pLeft;
        
                pNext = pRight;
            }
            else if(pNode->m_pParent != nullptr)
            {
                BinaryTreeNode* pCurrent = pNode;
                BinaryTreeNode* pParent = pNode->m_pParent;
                while(pParent != nullptr && pCurrent == pParent->m_pRight)
                {
                    pCurrent = pParent;
                    pParent = pParent->m_pParent;
                }
        
                pNext = pParent;
            }
        
            return pNext;
        }
        
        // ==================== 辅助代码用来构建二叉树 ====================
        BinaryTreeNode* CreateBinaryTreeNode(int value)
        {
            BinaryTreeNode* pNode = new BinaryTreeNode();
            pNode->m_nValue = value;
            pNode->m_pLeft = nullptr;
            pNode->m_pRight = nullptr;
            pNode->m_pParent = nullptr;
        
            return pNode;
        }
        
        void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
        {
            if(pParent != nullptr)
            {
                pParent->m_pLeft = pLeft;
                pParent->m_pRight = pRight;
        
                if(pLeft != nullptr)
                    pLeft->m_pParent = pParent;
                if(pRight != nullptr)
                    pRight->m_pParent = pParent;
            }
        }
        
        void PrintTreeNode(BinaryTreeNode* pNode)
        {
            if(pNode != nullptr)
            {
                printf("value of this node is: %d\n", pNode->m_nValue);
        
                if(pNode->m_pLeft != nullptr)
                    printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
                else
                    printf("left child is null.\n");
        
                if(pNode->m_pRight != nullptr)
                    printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
                else
                    printf("right child is null.\n");
            }
            else
            {
                printf("this node is null.\n");
            }
        
            printf("\n");
        }
        
        void PrintTree(BinaryTreeNode* pRoot)
        {
            PrintTreeNode(pRoot);
        
            if(pRoot != nullptr)
            {
                if(pRoot->m_pLeft != nullptr)
                    PrintTree(pRoot->m_pLeft);
        
                if(pRoot->m_pRight != nullptr)
                    PrintTree(pRoot->m_pRight);
            }
        }
        
        void DestroyTree(BinaryTreeNode* pRoot)
        {
            if(pRoot != nullptr)
            {
                BinaryTreeNode* pLeft = pRoot->m_pLeft;
                BinaryTreeNode* pRight = pRoot->m_pRight;
        
                delete pRoot;
                pRoot = nullptr;
        
                DestroyTree(pLeft);
                DestroyTree(pRight);
            }
        }
        
        // ====================测试代码====================
        void Test(char* testName, BinaryTreeNode* pNode, BinaryTreeNode* expected)
        {
            if(testName != nullptr)
                printf("%s begins: ", testName);
        
            BinaryTreeNode* pNext = GetNext(pNode);
            if(pNext == expected)
                printf("Passed.\n");
            else
                printf("FAILED.\n");
        }
        
        //            8
        //        6      10
        //       5 7    9  11
        void Test1_7()
        {
            BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
            BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
            BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
            BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
            BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
            BinaryTreeNode* pNode9 = CreateBinaryTreeNode(9);
            BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
        
            ConnectTreeNodes(pNode8, pNode6, pNode10);
            ConnectTreeNodes(pNode6, pNode5, pNode7);
            ConnectTreeNodes(pNode10, pNode9, pNode11);
        
            Test("Test1", pNode8, pNode9);
            Test("Test2", pNode6, pNode7);
            Test("Test3", pNode10, pNode11);
            Test("Test4", pNode5, pNode6);
            Test("Test5", pNode7, pNode8);
            Test("Test6", pNode9, pNode10);
            Test("Test7", pNode11, nullptr);
        
            DestroyTree(pNode8);
        }
        
        //            5
        //          4
        //        3
        //      2
        void Test8_11()
        {
            BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
            BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
            BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
            BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
        
            ConnectTreeNodes(pNode5, pNode4, nullptr);
            ConnectTreeNodes(pNode4, pNode3, nullptr);
            ConnectTreeNodes(pNode3, pNode2, nullptr);
        
            Test("Test8", pNode5, nullptr);
            Test("Test9", pNode4, pNode5);
            Test("Test10", pNode3, pNode4);
            Test("Test11", pNode2, pNode3);
        
            DestroyTree(pNode5);
        }
        
        //        2
        //         3
        //          4
        //           5
        void Test12_15()
        {
            BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
            BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
            BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
            BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
        
            ConnectTreeNodes(pNode2, nullptr, pNode3);
            ConnectTreeNodes(pNode3, nullptr, pNode4);
            ConnectTreeNodes(pNode4, nullptr, pNode5);
        
            Test("Test12", pNode5, nullptr);
            Test("Test13", pNode4, pNode5);
            Test("Test14", pNode3, pNode4);
            Test("Test15", pNode2, pNode3);
        
            DestroyTree(pNode2);
        }
        
        void Test16()
        {
            BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
        
            Test("Test16", pNode5, nullptr);
        
            DestroyTree(pNode5);
        }
        
        int main(int argc, char* argv[])
        {
            Test1_7();
            Test8_11();
            Test12_15();
            Test16();
        }

9、【剑指Offer学习】【面试题09:斐波那契数列】

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.
    
    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/
    
    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    // 面试题9:用两个栈实现队列
    // 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail
    // 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。
    
    #include "Queue.h"
    
    // ====================测试代码====================
    void Test(char actual, char expected)
    {
        if(actual == expected)
            printf("Test passed.\n");
        else
            printf("Test failed.\n");
    }
    
    int main(int argc, char* argv[])
    {
        CQueue<char> queue;
    
        queue.appendTail('a');
        queue.appendTail('b');
        queue.appendTail('c');
    
        char head = queue.deleteHead();
        Test(head, 'a');
    
        head = queue.deleteHead();
        Test(head, 'b');
    
        queue.appendTail('d');
        head = queue.deleteHead();
        Test(head, 'c');
    
        queue.appendTail('e');
        head = queue.deleteHead();
        Test(head, 'd');
    
        head = queue.deleteHead();
        Test(head, 'e');
    
        return 0;
    }
    

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.
    
    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/
    
    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    // 面试题9:用两个栈实现队列
    // 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail
    // 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。
    
    #pragma once
    #include <stack>
    #include <exception>
    
    using namespace std;
    
    template <typename T> class CQueue
    {
    public:
        CQueue(void);
        ~CQueue(void);
        
        // 在队列末尾添加一个结点
        void appendTail(const T& node);
    
        // 删除队列的头结点
        T deleteHead();
    
    private:
        stack<T> stack1;
        stack<T> stack2;
    };
    
    template <typename T> CQueue<T>::CQueue(void)
    {
    }
    
    template <typename T> CQueue<T>::~CQueue(void)
    {
    }
    
    template<typename T> void CQueue<T>::appendTail(const T& element)
    {
        stack1.push(element);
    } 
    
    template<typename T> T CQueue<T>::deleteHead()
    {
        if(stack2.size()<= 0)
        {
            while(stack1.size()>0)
            {
                T& data = stack1.top();
                stack1.pop();
                stack2.push(data);
            }
        }
    
        if(stack2.size() == 0)
            throw new exception("queue is empty");
    
        T head = stack2.top();
        stack2.pop();
    
        return head;
    }

10、【剑指Offer学习】【面试题10:二进制中1 的个数】

            /*******************************************************************
            Copyright(c) 2016, Harry He
            All rights reserved.
            
            Distributed under the BSD license.
            (See accompanying file LICENSE.txt at
            https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
            *******************************************************************/
            
            //==================================================================
            // 《剑指Offer——名企面试官精讲典型编程题》代码
            // 作者:何海涛
            //==================================================================
            
            // 面试题10:斐波那契数列
            // 题目:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。
            
            #include <cstdio>
            
            // ====================方法1:递归====================
            long long Fibonacci_Solution1(unsigned int n)
            {
                if(n <= 0)
                    return 0;
            
                if(n == 1)
                    return 1;
            
                return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);
            }
            
            // ====================方法2:循环====================
            long long Fibonacci_Solution2(unsigned n)
            {
                int result[2] = {0, 1};
                if(n < 2)
                    return result[n];
            
                long long  fibNMinusOne = 1;
                long long  fibNMinusTwo = 0;
                long long  fibN = 0;
                for(unsigned int i = 2; i <= n; ++ i)
                {
                    fibN = fibNMinusOne + fibNMinusTwo;
            
                    fibNMinusTwo = fibNMinusOne;
                    fibNMinusOne = fibN;
                }
            
                 return fibN;
            }
            
            // ====================方法3:基于矩阵乘法====================
            #include <cassert>
            
            struct Matrix2By2
            {
                Matrix2By2
                (
                    long long m00 = 0, 
                    long long m01 = 0, 
                    long long m10 = 0, 
                    long long m11 = 0
                )
                :m_00(m00), m_01(m01), m_10(m10), m_11(m11) 
                {
                }
            
                long long m_00;
                long long m_01;
                long long m_10;
                long long m_11;
            };
            
            Matrix2By2 MatrixMultiply
            (
                const Matrix2By2& matrix1, 
                const Matrix2By2& matrix2
            )
            {
                return Matrix2By2(
                    matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
                    matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
                    matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
                    matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);
            }
            
            Matrix2By2 MatrixPower(unsigned int n)
            {
                assert(n > 0);
            
                Matrix2By2 matrix;
                if(n == 1)
                {
                    matrix = Matrix2By2(1, 1, 1, 0);
                }
                else if(n % 2 == 0)
                {
                    matrix = MatrixPower(n / 2);
                    matrix = MatrixMultiply(matrix, matrix);
                }
                else if(n % 2 == 1)
                {
                    matrix = MatrixPower((n - 1) / 2);
                    matrix = MatrixMultiply(matrix, matrix);
                    matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
                }
            
                return matrix;
            }
            
            long long Fibonacci_Solution3(unsigned int n)
            {
                int result[2] = {0, 1};
                if(n < 2)
                    return result[n];
            
                Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
                return PowerNMinus2.m_00;
            }
            
            // ====================测试代码====================
            void Test(int n, int expected)
            {
                if(Fibonacci_Solution1(n) == expected)
                    printf("Test for %d in solution1 passed.\n", n);
                else
                    printf("Test for %d in solution1 failed.\n", n);
            
                if(Fibonacci_Solution2(n) == expected)
                    printf("Test for %d in solution2 passed.\n", n);
                else
                    printf("Test for %d in solution2 failed.\n", n);
            
                if(Fibonacci_Solution3(n) == expected)
                    printf("Test for %d in solution3 passed.\n", n);
                else
                    printf("Test for %d in solution3 failed.\n", n);
            }
            
            int main(int argc, char* argv[])
            {
                Test(0, 0);
                Test(1, 1);
                Test(2, 1);
                Test(3, 2);
                Test(4, 3);
                Test(5, 5);
                Test(6, 8);
                Test(7, 13);
                Test(8, 21);
                Test(9, 34);
                Test(10, 55);
            
                Test(40, 102334155);
            
                return 0;
            }
            

猜你喜欢

转载自www.cnblogs.com/agui125/p/12020184.html