剑指offer|解析和答案(C++/Python) (一)
参考剑指offer(第二版),这里做一个学习汇总,包括解析及代码。代码均在牛客网进行验证(摘自自己的牛客网笔记)。
整个剑指offer解析链接:
剑指offer|解析和答案(C++/Python) (一).
剑指offer|解析和答案(C++/Python) (二).
剑指offer|解析和答案(C++/Python) (三).
剑指offer|解析和答案(C++/Python) (四).
剑指offer|解析和答案(C++/Python) (五)上.
剑指offer|解析和答案(C++/Python) (五)下.
剑指offer|解析和答案(C++/Python) (六).
习题
面试需要的基础知识
1.数组中重复的数字
2.二维数组中的查找
3.替换空格
4.从头到尾打印链表
5.重建二叉树
6.二叉树的下一个节点
7.用两个栈实现队列
8.斐波那契数列
9.旋转数组的最小数字
10.矩阵中的路径
11.机器人的运动范围
12.剪绳子
13.二进制中1的个数
14.跳台阶
1.数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路:
1.使用哈希表。将哈希表初始化为0,然后从头到尾扫描数组的每个数字,每扫到一个数字的时候,可以用O(1)的时间复杂度判断哈希表里面是否包含了该数字。如果有则加1。扫描完后,从头到尾扫描哈希表,只要对应的数值大于1,则有重复的数字,返回true。遍历完没有大于1的,则返回false。
代码:
C++
class Solution {
public:
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
bool duplicate(int numbers[], int length, int* duplication) {
vector<int> completeNum;
for(int i = 0; i < length; ++i){
completeNum.push_back(0);
}
for(int i = 0; i < length; ++i){
++completeNum[numbers[i]];
}
for(int i = 0; i < length; ++i){
if(completeNum[i]>1){
*duplication = i;
return true;
}
}
return false;
}
};
2.使用哈希表的时间复杂度是O(n),空间复杂度是O(n),还有可以优化的空间。使用数值和ID交换的思路,可以实现空间复杂度是O(1)的算法。
数组数字的范围是0~n-1。如果数组中没有重复的数字,那么当数组排序之后数字i将出现在下标为i的位置,如果数组中有重复的数字,那么必定会出现数字i不仅仅出现在下标为i的位置,还可能出现在下标为m、x…的位置,只要发现下标为m和下标为i的数字相同,则发现有重复的数字,返回ture。
代码:
C++
class Solution {
public:
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
bool duplicate(int numbers[], int length, int* duplication) {
for(int i = 0; i < length; ++i){
while(i != numbers[i]){
//判断
if(numbers[i] == numbers[numbers[i]]){
//找到重复的数字
*duplication = numbers[i];
return true;
}
//交换顺序
int temp = numbers[i];
numbers[i] = numbers[temp];
numbers[temp] = temp;
}
}
return false;
}
};
Python
# -*- coding:utf-8 -*-
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
for i in range(len(numbers)):
#对应位置上的元素不相等
while numbers[i] != i:
#判断
if numbers[i] == numbers[numbers[i]]:
#找到重复的数字
duplication[0] = numbers[i]
return True
#交换位置
temp = numbers[i]
numbers[i] = numbers[temp]
numbers[temp] = temp
#没有找到重复的
return False
2.二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:
从右上角元素为参考元素,每次和target进行比较。如果target等于参考元素,那么返回true,如果不是进行比较。1.target大于参考元素,则排除该行。2.如果target小于参考元素,则排除该列。一次类推,直到达到边界条件,如果还没有没有找到,则返回false。
C++
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int cols = array[0].size();
int rows = array.size();
if( array.empty()==0 && cols > 0 && rows > 0){
//查找右上角的元素
int col = cols - 1;
int row = 0;
//如果target大于该元素,则排除该行,如果target小于该元素,排除该列
while( col >= 0 && row < rows){
if( target == array[row][col]){
return true;
}else if( target > array[row][col]){
++row;
}else if( target < array[row][col]){
--col;
}
}
}
return false;
}
};
Python
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
cols = len(array[0])
rows = len(array)
if cols > 0 and rows > 0:
col = cols - 1
row = 0
while row < rows and col >= 0 :
if target == array[row][col]:
return 1
elif target < array[row][col]:
col = col - 1
else :
row = row +1
return 0
3.替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
思路
两个方向
1.正向查找,找到’ ‘就把后面的字符数组后移2位,同时把’ ‘替换为’%20‘。但是这样每找到’ '就后把后面的所以字符数组移动,假设这个字符数组长度为n,时间复杂度为O(n^2)。
2.反向查找,对原字符数组进行“扩容”,计算所有的’ ‘的个数,一个指针指向“扩容”数组的最后一个,一个指针指向“原”数组的最后一个,依次赋值移动。
C++
class Solution{
public:
//length 为字符数组str的总容量
void replaceSpace(char*str,int length) {
//特殊情况判断
if( str == nullptr||length <= 0){
return;
}
//记录空格数目
int originalLength = 0;//计算原字符串实际长度
int numberOfBlank = 0;//记录空格数目
int i = 0;
while(str[i] !='\0'){
++originalLength;
if( str[i] ==' '){
++numberOfBlank;
}
++i;
}
//判断是否超出容量
int newLength = originalLength + 2*numberOfBlank;
if(newLength > length){
return;
}
int indexOfOriginal = originalLength;
int indexOfNew = newLength;//倒序排列赋值
while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal){
//注意originalLength是排除'\0'之后的长度,
//所以第一次进入循环时:str[originalLength] = '\0'
if( str[indexOfOriginal] ==' '){
str[indexOfNew--] ='0';
str[indexOfNew--] ='2';
str[indexOfNew--] ='%';
}else{
str[indexOfNew--] = str[indexOfOriginal];
}
--indexOfOriginal;
}
}
};
Python
class Solution:
# s 源字符串
def replaceSpace(self, s):
# write code here
originalLength = len(s)
#记录空格数
i = 0
numberOfBlank = 0
while i < originalLength:
if s[i] == ' ':
numberOfBlank = numberOfBlank + 1
i = i + 1
newLength = originalLength + 2*numberOfBlank
indexOriginal = originalLength - 1
indexNewstr = newLength - 1
#python的string类型不允许改变 新建一个string
new_string = [None for i in range(newLength)]
while indexOriginal >= 0 :
if s[indexOriginal] == ' ':
new_string[indexNewstr] = '0'
new_string[indexNewstr - 1] = '2'
new_string[indexNewstr - 2] = '%'
indexNewstr = indexNewstr - 3
else :
new_string[indexNewstr] = s[indexOriginal]
indexNewstr = indexNewstr - 1
indexOriginal = indexOriginal -1
return ''