剑指offer面试题汇总(算法和数据操作)

剑指offer面试案例汇总(算法和数据操作)

    • 面试题10:斐波那契数列&青蛙跳台阶
      • 递归
      • 自低向上
      • 相关题目
    • 面试题11:旋转数组最小数字
      • 解题思路
      • 答案代码
    • 面试题12:矩阵中的路径
    • 面试题13:机器人的运动范围
    • 解题思路
    • 面试题14:剪绳子
      • 动态规划
      • 贪心算法
    • 面试题15:二进制中1的个数
      • 解题方法
      • Great

面试题10:斐波那契数列&青蛙跳台阶

求斐波那契数列的第n项。

递归

long long Fibonacci(unsigned int n)
{
	if(n==0)	return 0;
	else if(n==1)	return 1;
	else return Fibonacci(n-1) + Fibonacci(n-2);
}

自低向上

long long Fibonacci(unsigned n)
{
	int result[2] = {0, 1};
	if(n<2)	return result[n];
	long long f1;
	long long f2;
	long long fn;
	for(unsigned int i=2; i<=n; i++)
	{
		fn = f1+f2;
		f1 = f2;
		f2 = fn;
	}
	return fn;
}

青蛙跳台阶
一只青蛙一次可以跳上1级台阶,也可跳上2级台阶。求青蛙跳上n级台阶共多少种跳法

转变为fabonacci的应用:第n阶台阶的跳法=第n-1阶的跳法(+1阶) + 第n-2阶的跳法(+2阶)

相关题目

可以用21的小矩形横着或竖着去覆盖更大的矩形,请问用8个21的小矩形无重叠覆盖一个2*8的大矩形共有多少种方法

依然是斐波那契数列

面试题11:旋转数组最小数字

查找和排序

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

解题思路

直接遍历的话时间复杂度为 O ( n ) O(n) O(n),选择利用二分排序的方法
我的代码:

void FindMax(vector A,  int &res)
{
    int left = 0, right = A.size()-1;
    int mid = (left+right)/2;
    int min = INT_MAX;
    while(left!=right-1)
    {
        mid = (left+right)/2;
        if(A[mid]A[left])
        {
            left = mid;
        }
        if(min>A[mid])
        {
            min = A[mid];
        }
    }
    res = min;
   }

答案代码

int Min(int *numbers, int length)
{
	if(numbers == nullptr || length <= 0)
	{
		throw new std::exception("Invaild parameters");
	}
	int index1 = 0;
	int index2 = length-1;
	int indexMid = index1;
	while(numbers[index1] >= numbers[index2])
	{
		if(index2 - index1 ==1)
		{
			indexMid = index2;
			break;
		}
		indexMid = (index1 + index2)/2;
		if(numbers[indexMid] >= numbers[index1])
		{
			index1 = indexMid;
		}
		else if(numbers[indexMid]<=numbers[index2])
		{
			index2 = indexMid;
		}
		
	}
	return numbers[indexMid];
}

面试题12:矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次经过该格。

路径可以被看成一个栈,第n个字符周围没有第n+1个字符时,回到n-1;

bool hasPath(char *matrix, int rows. int cols, 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=0 && row=0 && col

面试题13:机器人的运动范围

地上有一个m行n列的方格。一个机器人从坐标(0, 0)的格子开始移动,它每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的位数之和大于k的格子。
例如,当k=18, 机器人能进入方格(35, 37),3+5+3+7=18。请问该机器人能够到达多少个格子?

解题思路

  1. 移动
  2. 判断
int movingCountCore(int threshold, int rows, int cols, int row, int col, bool* visited);
bool check(int threshold, int rows, int cols, int row, int col, bool* visited);
int getDigitSum(int number);

int movingCount(int threshold, int rows, int cols)
{
    if(threshold < 0 || rows <= 0 || cols <= 0)
        return 0;

    bool *visited = new bool[rows * cols];
    for(int i = 0; i < rows * cols; ++i)
        visited[i] = false;

    int count = movingCountCore(threshold, rows, cols,
        0, 0, visited);

    delete[] visited;

    return count;
}

int movingCountCore(int threshold, int rows, int cols, int row,
    int col, bool* visited)
{
    int count = 0;
    if(check(threshold, rows, cols, row, col, visited))
    {
        visited[row * cols + col] = true;

        count = 1 + movingCountCore(threshold, rows, cols,
            row - 1, col, visited)
            + movingCountCore(threshold, rows, cols,
                row, col - 1, visited)
            + movingCountCore(threshold, rows, cols,
                row + 1, col, visited)
            + movingCountCore(threshold, rows, cols,
                row, col + 1, visited);
    }

    return count;
}

bool check(int threshold, int rows, int cols, int row, int col,
    bool* visited)
{
    if(row >= 0 && row < rows && col >= 0 && col < cols
        && getDigitSum(row) + getDigitSum(col) <= threshold
        && !visited[row* cols + col])
        return true;

    return false;
}

int getDigitSum(int number)
{
    int sum = 0;
    while(number > 0)
    {
        sum += number % 10;
        number /= 10;
    }

    return sum;
}

哭辽,两个题没了!

面试题14:剪绳子

给你一根长度为n的绳子,请把绳子剪成m段,使得每段乘积最大

动态规划

贪心算法

面试题15:二进制中1的个数

请实现一个函数,输入一个整数,输出该数二进制表示中1的个数

解题方法

我的笨办法

int CountOne(int num)
{
    int count =0;
    while(num!=0)
    {
        if(num % 2 == 1)    count++;
        num = num/2;
    }
    return count;
}

哎呀,还得考虑符号位

右移也是除以2,并且右移的效率高很多。

先把n和1做与运算,判断最低位是不是1。再把n左移一位,再与n做与运算,判断n的次低位是不是1。
这样每次判断n的一位是不是1


int NumberOf1(int n)
{
	int count =0;
	unsigned int flag = 1;
	while(flag)
	{
		if(n&flag)	count ++;
		flag = flag << 1;
	}
	return count;
}

上述方法32位n循环32次

Great

把一个整数减去1,再和原整数做与运算,会把该整数的最右边的1变成0;

int NumberOf1(int n)
{
	int count = 0;
	while(n)
	{
		++ count;
		n = (n-1) & n;
	}
	return count;
}

你可能感兴趣的:(C++,算法)