day6-day9代码片段

本文精选了多个经典的编程问题,包括模拟实现atoi函数、利用前序和中序遍历重建二叉树、求解斐波那契数列、寻找旋转数组中的最小数字、判断矩阵中的路径存在性、剪绳子问题、计算二进制中1的个数、确定机器人的运动范围、计算数值的整数次方。每个问题都提供了详细的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 模拟实现atoi

#include<iostream>
#include<cassert>
using namespace std;
enum Legal{valid=0,legal=1};
int flag = 1;
int fuhao = 1;
int strToInt(const char *str)
{
    long long num = 0;
    while (*str != '\0')
    {
        if (*str >= '0'&&*str <= '9')
        {
            num = num * 10 + fuhao*(*str - '0');
            if ((1 == fuhao&&num > 0x7fffffff) || -1 == fuhao&&num < (signed int)0x80000000)
            {
                num = 0;
                break;
            }
            ++str;
        }
        else
        {
            num = 0;
            break;
        }
    }
    if (*str == '\0')
        flag = legal;
    return num;
}
int Atoi(const char *str)
{
    assert(str);
    long long num = 0;
    while (' ' == *str)
        ++str;
    if (*str != '\0')
    {
        if ('-' == *str)
        {
            ++str;
            fuhao = -1;
        }
        else if ('+' == *str)
            ++str;
        else
        {
            flag = valid;
        }
        if (*str != '\0')
        {
            num = strToInt(str);
        }
    }
    return (int)num;
}
int main()
{
    char *str = " -1234";
    int res=Atoi(str);
    cout << res << endl;
    system("pause");
}

2. 前序中序遍历重建二叉树

这里写图片描述

/*
 由前序遍历和中序遍历重建二叉树(前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5)

分析:
   先序遍历:访问当前结点,访问左子树,访问右子树.
   中序遍历:访问左子树,访问当前结点,访问右子树.
   可以发现,前序遍历的每一结点,都是当前子树的根节点,我们可以根据前序遍历的序列对中序遍历的序列进行划分。
*/
void CreatSubTree(BinaryTreeNode<int>* &root,
    int* InOrder,
    int *PrevOrder,
    int len)
{
    if (len<=0)
        return;

    root= new BinaryTreeNode<int>(PrevOrder[0]);
    int index = 0;           //父节点在数组中的下标
    for (; index < len; ++index)
    {
        if (PrevOrder[0] == InOrder[index])
            break;
    }
    int subTreeL =index;                     //左子树结点个数
    int subTreeR = len - index - 1;               //右子树结点个数
    CreatSubTree(root->_left, InOrder, PrevOrder + 1, subTreeL);
    CreatSubTree(root->_right,InOrder + index + 1, PrevOrder + index + 1, subTreeR);
}


BinaryTreeNode<int>* RebuildBinaryTree(int *InOrder, int *PrevOrder, int len)
{
    assert(InOrder);
    assert(PrevOrder);
    BinaryTreeNode<int>* root;
    CreatSubTree(root, InOrder, PrevOrder,len);
    return root;
}

3. 斐波那契数列

/*
    变形:1. 青蛙跳台阶
         2. 青蛙变态跳台阶
         3. 瓷砖横放或竖放
*/
#include<iostream>
using namespace std;
//递归版
int getFeiBo(const size_t n)
{
    if (n <=0)
        return 0;
    if (1 == n)
        return 1;
    return getFeiBo(n - 1) + getFeiBo(n - 2);
}
//循环版
int getFeiBoLoop(const size_t n)
{
    int a = 1;
    int b = 1;
    int c = 1;
    for (int i = 2; i < n; i++)
    {
        c = a + b;
        a = b;
        b = c;
    }
    return c;
}
int main()
{
    int n;
    while (cin >> n)
        cout << getFeiBoLoop(n) << endl;
    return 0;
}

4. 二分查找变形旋转数组中的最小数字

/*******************************************************************
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——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题11:旋转数组的最小数字
// 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
// 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组
// {3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

#include <cstdio>
#include <exception>

int MinInOrder(int* numbers, int begin, int end);

int Min(int* numbers, int length)
{
    if (numbers == nullptr || length <= 0)
        throw new std::exception("Invalid parameters");

    int begin = 0;
    int end = length - 1;
    int indexMid = begin;
    while (numbers[begin] >= numbers[end])
    {
        // 如果begin和end指向相邻的两个数,
        // 则begin指向第一个递增子数组的最后一个数字,
        // end指向第二个子数组的第一个数字,也就是数组中的最小数字
        if (end - begin == 1)
        {
            indexMid = end;
            break;
        }

        // 如果下标为begin、end和indexMid指向的三个数字相等,
        // 则只能顺序查找
        indexMid = (begin + end) / 2;
        if (numbers[begin] == numbers[end] && numbers[indexMid] == numbers[begin])
            return MinInOrder(numbers, begin, end);

        // 缩小查找范围
        if (numbers[indexMid] >= numbers[begin])
            begin = indexMid;
        else if (numbers[indexMid] <= numbers[end])
            end = indexMid;
    }

    return numbers[indexMid];
}

int MinInOrder(int* numbers, int begin, int end)
{
    int result = numbers[begin];
    for (int i = begin + 1; i <= end; ++i)
    {
        if (result > numbers[i])
            result = numbers[i];
    }

    return result;
}

// ====================测试代码====================
void Test(int* numbers, int length, int expected)
{
    int result = 0;
    try
    {
        result = Min(numbers, length);

        for (int i = 0; i < length; ++i)
            printf("%d ", numbers[i]);

        if (result == expected)
            printf("\tpassed\n");
        else
            printf("\tfailed\n");
    }
    catch (...)
    {
        if (numbers == nullptr)
            printf("Test passed.\n");
        else
            printf("Test failed.\n");
    }
}

int main(int argc, char* argv[])
{
    // 典型输入,单调升序的数组的一个旋转
    int array1[] = { 3, 4, 5, 1, 2 };
    Test(array1, sizeof(array1) / sizeof(int), 1);

    // 有重复数字,并且重复的数字刚好的最小的数字
    int array2[] = { 3, 4, 5, 1, 1, 2 };
    Test(array2, sizeof(array2) / sizeof(int), 1);

    // 有重复数字,但重复的数字不是第一个数字和最后一个数字
    int array3[] = { 3, 4, 5, 1, 2, 2 };
    Test(array3, sizeof(array3) / sizeof(int), 1);

    // 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字
    int array4[] = { 1, 0, 1, 1, 1 };
    Test(array4, sizeof(array4) / sizeof(int), 0);

    // 单调升序数组,旋转0个元素,也就是单调升序数组本身
    int array5[] = { 1, 2, 3, 4, 5 };
    Test(array5, sizeof(array5) / sizeof(int), 1);

    // 数组中只有一个数字
    int array6[] = { 2 };
    Test(array6, sizeof(array6) / sizeof(int), 2);

    // 输入nullptr
    Test(nullptr, 0, 0);
    system("pause");
    return 0;
}

5. 面试题12:矩阵中的路径

/*******************************************************************
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——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题12:矩阵中的路径
// 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H

#include <cstdio>
#include <string>
#include <stack>

using namespace std;

bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int& pathLength, bool* visited);

bool hasPath(const char* matrix, int rows, int cols, const char* str)
{
    if(matrix == nullptr || rows < 1 || cols < 1 || str == nullptr)
        return false;

    bool *visited = new bool[rows * cols];
    memset(visited, 0, rows * cols);

    int pathLength = 0;
    for(int row = 0; row < rows; ++row)
    {
        for(int col = 0; col < cols; ++col)
        {
            if(hasPathCore(matrix, rows, cols, row, col, str,
                pathLength, visited))
            {
                return true;
            }
        }
    }

    delete[] visited;

    return false;
}

bool hasPathCore(const char* matrix, int rows, int cols, int row,
    int col, const char* str, int& pathLength, bool* visited)
{
    if(str[pathLength] == '\0')
        return true;

    bool hasPath = false;
    if(row >= 0 && row < rows && col >= 0 && col < cols
        && matrix[row * cols + col] == str[pathLength]
        && !visited[row * cols + col])
    {
        ++pathLength;
        visited[row * cols + col] = true;

        hasPath = hasPathCore(matrix, rows, cols, row, col - 1,
            str, pathLength, visited)
            || hasPathCore(matrix, rows, cols, row - 1, col,
                str, pathLength, visited)
            || hasPathCore(matrix, rows, cols, row, col + 1,
                str, pathLength, visited)
            || hasPathCore(matrix, rows, cols, row + 1, col,
                str, pathLength, visited);

        if(!hasPath)
        {
            --pathLength;
            visited[row * cols + col] = false;
        }
    }

    return hasPath;
}

// ====================测试代码====================
void Test(const char* testName, const char* matrix, int rows, int cols, const char* str, bool expected)
{
    if(testName != nullptr)
        printf("%s begins: ", testName);

    if(hasPath(matrix, rows, cols, str) == expected)
        printf("Passed.\n");
    else
        printf("FAILED.\n");
}

//ABTG
//CFCS
//JDEH

//BFCE
void Test1()
{
    const char* matrix = "ABTGCFCSJDEH";
    const char* str = "BFCE";

    Test("Test1", (const char*) matrix, 3, 4, str, true);
}

//ABCE
//SFCS
//ADEE

//SEE
void Test2()
{
    const char* matrix = "ABCESFCSADEE";
    const char* str = "SEE";

    Test("Test2", (const char*) matrix, 3, 4, str, true);
}

//ABTG
//CFCS
//JDEH

//ABFB
void Test3()
{
    const char* matrix = "ABTGCFCSJDEH";
    const char* str = "ABFB";

    Test("Test3", (const char*) matrix, 3, 4, str, false);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SLHECCEIDEJFGGFIE
void Test4()
{
    const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
    const char* str = "SLHECCEIDEJFGGFIE";

    Test("Test4", (const char*) matrix, 5, 8, str, true);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SGGFIECVAASABCEHJIGQEM
void Test5()
{
    const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
    const char* str = "SGGFIECVAASABCEHJIGQEM";

    Test("Test5", (const char*) matrix, 5, 8, str, true);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SGGFIECVAASABCEEJIGOEM
void Test6()
{
    const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
    const char* str = "SGGFIECVAASABCEEJIGOEM";

    Test("Test6", (const char*) matrix, 5, 8, str, false);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SGGFIECVAASABCEHJIGQEMS
void Test7()
{
    const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
    const char* str = "SGGFIECVAASABCEHJIGQEMS";

    Test("Test7", (const char*) matrix, 5, 8, str, false);
}

//AAAA
//AAAA
//AAAA

//AAAAAAAAAAAA
void Test8()
{
    const char* matrix = "AAAAAAAAAAAA";
    const char* str = "AAAAAAAAAAAA";

    Test("Test8", (const char*) matrix, 3, 4, str, true);
}

//AAAA
//AAAA
//AAAA

//AAAAAAAAAAAAA
void Test9()
{
    const char* matrix = "AAAAAAAAAAAA";
    const char* str = "AAAAAAAAAAAAA";

    Test("Test9", (const char*) matrix, 3, 4, str, false);
}

//A

//A
void Test10()
{
    const char* matrix = "A";
    const char* str = "A";

    Test("Test10", (const char*) matrix, 1, 1, str, true);
}

//A

//B
void Test11()
{
    const char* matrix = "A";
    const char* str = "B";

    Test("Test11", (const char*) matrix, 1, 1, str, false);
}

void Test12()
{
    Test("Test12", nullptr, 0, 0, nullptr, false);
}

int main(int argc, char* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Test7();
    Test8();
    Test9();
    Test10();
    Test11();
    Test12();

    return 0;
}

6. 剪绳子


// 面试题14:剪绳子
// 题目:给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。
// 每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]*k[1]*…*k[m]可能的最大乘
// 积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此
// 时得到最大的乘积18。
/*动态规划*/
#include<iostream>
using namespace std;
int Max(int length)
{
    if (length < 2)
        return 0;
    if (length == 2)
        return 1;
    if (length == 3)
        return 2;
    int *arr = new int[length + 1];
    arr[0] = 0;
    arr[1] = 1;
    arr[2] = 2;
    arr[3] = 3;
    int max = 0;
    for (int i = 4; i <= length; ++i)
    {
        max = 0;
        for (int j = 1; j <= i / 2; ++j)
        {
            int a = arr[j] * arr[i - j];
            if (max < a)
                max = a;
            arr[i] = max;
        }
    }
    max = arr[length];
    delete[] arr;
    return max;
}

// ====================贪婪算法====================
int maxProductAfterCutting_solution2(int length)
{
    if(length < 2)
        return 0;
    if(length == 2)
        return 1;
    if(length == 3)
        return 2;

    // 尽可能多地减去长度为3的绳子段
    int timesOf3 = length / 3;

    // 当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子段。
    // 此时更好的方法是把绳子剪成长度为2的两段,因为2*2 > 3*1。
    if(length - timesOf3 * 3 == 1)
        timesOf3 -= 1;

    int timesOf2 = (length - timesOf3 * 3) / 2;

    return (int) (pow(3, timesOf3)) * (int) (pow(2, timesOf2));
}

// ====================测试代码====================
void test(const char* testName, int length, int expected)
{
    int result1 = maxProductAfterCutting_solution1(length);
    if(result1 == expected)
        std::cout << "Solution1 for " << testName << " passed." << std::endl;
    else
        std::cout << "Solution1 for " << testName << " FAILED." << std::endl;

    int result2 = maxProductAfterCutting_solution2(length);
    if(result2 == expected)
        std::cout << "Solution2 for " << testName << " passed." << std::endl;
    else
        std::cout << "Solution2 for " << testName << " FAILED." << std::endl;
}

void test1()
{
    int length = 1;
    int expected = 0;
    test("test1", length, expected);
}

void test2()
{
    int length = 2;
    int expected = 1;
    test("test2", length, expected);
}

void test3()
{
    int length = 3;
    int expected = 2;
    test("test3", length, expected);
}

void test4()
{
    int length = 4;
    int expected = 4;
    test("test4", length, expected);
}

void test5()
{
    int length = 5;
    int expected = 6;
    test("test5", length, expected);
}

void test6()
{
    int length = 6;
    int expected = 9;
    test("test6", length, expected);
}

void test7()
{
    int length = 7;
    int expected = 12;
    test("test7", length, expected);
}

void test8()
{
    int length = 8;
    int expected = 18;
    test("test8", length, expected);
}

void test9()
{
    int length = 9;
    int expected = 27;
    test("test9", length, expected);
}

void test10()
{
    int length = 10;
    int expected = 36;
    test("test10", length, expected);
}

void test11()
{
    int length = 50;
    int expected = 86093442;
    test("test11", length, expected);
}

int main(int agrc, char* argv[])
{
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    test8();
    test9();
    test10();
    test11();

    return 0;
}

7. 二进制中1的个数

#include<iostream>
using namespace std;
/*
    注意若这样写:
    n&1;n>>1;
    count++;
    如果是负数会造成死循环复数右移时为保证移位后仍是复数为补1
    如:0x80000000右移移位不会变成0x40000000而是会变成
    0xc0000000若一直右移最后会变成0xFFFFFFFF
    应该这样写
    i=1;
    n&i;i<<=1;count++;
    count++;
*/
int getCount(int n)
{
    int count = 0;
    while (n)
    {
        n &= (n - 1);
        count++;
    }
    return count;
}
int main()
{
    int n;
    while (cin >> n)
        cout << getCount(n) << endl;
    return 0;
}

8. 机器人的运动范围

#include<iostream>
using namespace std;
int getSum(int n)
{
    int sum = 0;
    while (n > 0)
    {
        sum += n % 10;
        n /= 10;
    }
    return sum;
}
bool check(int boundary, int rows, int cols, int i, int j, bool *visited)
{
    if (i < rows&&i >= 0 && j < cols&&j >= 0 && getSum(i) + getSum(j) <= boundary&&!visited[i*cols + j])
        return true;
    return false;
}
int getCount(int boundary, int rows, int cols, int i, int j, bool *visited)
{
    int count = 0;
    if (check(boundary, rows, cols, i, j, visited))
    {
        visited[i*cols + j] = true;
        count = 1 + getCount(boundary, rows, cols, i + 1, j, visited)
            + getCount(boundary, rows, cols, i, j + 1, visited)
            + getCount(boundary, rows, cols, i - 1, j, visited)
            + getCount(boundary, rows, cols, i, j - 1, visited);
    }
    return count;
}
int movingCount(int boundary, int rows, int cols)
{
    if (boundary < 0 && rows <= 0 && cols <= 0)
        return 0;
    bool *visited = new bool[rows*cols];
    memset(visited, 0, rows*cols);
    int count = getCount(boundary, rows, cols,0,0, visited);
    delete[]visited;
    return count;
}
void test(char* testName, int threshold, int rows, int cols, int expected)
{
    if (testName != nullptr)
        printf("%s begins: ", testName);

    if (movingCount(threshold, rows, cols) == expected)
        printf("Passed.\n");
    else
        printf("FAILED.\n");
}

// 方格多行多列
void test1()
{
    test("Test1", 5, 10, 10, 21);
}

// 方格多行多列
void test2()
{
    test("Test2", 15, 20, 20, 359);
}

// 方格只有一行,机器人只能到达部分方格
void test3()
{
    test("Test3", 10, 1, 100, 29);
}

// 方格只有一行,机器人能到达所有方格
void test4()
{
    test("Test4", 10, 1, 10, 10);
}

// 方格只有一列,机器人只能到达部分方格
void test5()
{
    test("Test5", 15, 100, 1, 79);
}

// 方格只有一列,机器人能到达所有方格
void test6()
{
    test("Test6", 15, 10, 1, 10);
}

// 方格只有一行一列
void test7()
{
    test("Test7", 15, 1, 1, 1);
}

// 方格只有一行一列
void test8()
{
    test("Test8", 0, 1, 1, 1);
}

// 机器人不能进入任意一个方格
void test9()
{
    test("Test9", -10, 10, 10, 0);
}

int main(int agrc, char* argv[])
{
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    test8();
    test9();
    system("pause");
    return 0;
}

9. 数值的整数次方

#include<iostream>
using namespace std;
double Power(double base, size_t e)
{
    if (e == 0)
        return 1;
    if (e == 1)
        return base;
    double res = Power(base, e >> 1);
    res *= res;
    if ((e & 1) == 1)
        res *= base;
    return res;

}
int main()
{
    int base;
    int e;
    cin >> base;
    cin >> e;
    cout << Power(base, e);
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值