3.二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:从右上角开始,不断缩小行数或者列数
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
bool found = false;
if(array.empty() || array[0].empty()) return false;
int rows = array.size(), row = 0;
int cols = array[0].size(), col = cols - 1;
while(row < rows && col >= 0)
{
if(array[row][col] < target)
++row;
else if(array[row][col] > target)
--col;
else
{
found = true;
break;
}
}
return found;
}
};
4.替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
思路:确定新字符串的长度,从尾到头赋值,避免移动。
class Solution {
public:
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 + numberOfBlank * 2;
if(newLength > length) return;
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal >= 0 && newLength > originalLength){
if(str[indexOfOriginal] == ' '){
str[indexOfNew--] = '0';
str[indexOfNew--] = '2';
str[indexOfNew--] = '%';
}
else{
str[indexOfNew--] = str[indexOfOriginal];
}
--indexOfOriginal;
}
}
};
5.从尾到头打印链表
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
思路:利用栈结构实现。也可以利用递归,但是要避免栈溢出。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
stack<ListNode*> nodes;
vector<int> result;
ListNode* node = head;
while(node != NULL){
nodes.push(node);
node = node -> next;
}
while(!nodes.empty()){
result.push_back(nodes.top()->val);
nodes.pop();
}
return result;
}
};
6.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:下面用的LeetCode里的方法,比较后还是书上的方法好,易读、鲁棒,有时间改
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
return create(pre, vin, 0, pre.size() - 1, 0, vin.size() - 1);
}
private:
TreeNode* create(vector<int>& preorder, vector<int>& inorder, int ps, int pe, int is, int ie){
if(ps > pe){
return nullptr;
}
TreeNode* node = new TreeNode(preorder[ps]);
int pos;
for(int i = is; i <= ie; i++){
if(inorder[i] == node->val){
pos = i;
break;
}
}
node->left = create(preorder, inorder, ps + 1, ps + pos - is, is, pos - 1);
node->right = create(preorder, inorder, pe - ie + pos + 1, pe, pos + 1, ie);
return node;
}
};
7.用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:第1个负责压入数据,第2个负责输出。当第2个栈为空时将第1个栈的数据全部压入到第2个栈。
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if(stack2.size() <= 0){
while(stack1.size() > 0){
stack2.push(stack1.top());
stack1.pop();
}
}
//if(stack2.size() == 0)
//throw new exception("queue is empty");
int node = stack2.top();
stack2.pop();
return node;
}
private:
stack<int> stack1;
stack<int> stack2;
};
8.旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:二分查找,LeetCode里要求返回bool类型,这里要求返回值。因为可重复,所以考虑到左右端点与中点值相等的情况,此时只能用顺序查找。
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.empty()) return 0;
int index1 = 0;
int index2 = rotateArray.size() - 1;
int indexMid = index1;
while(rotateArray[index1] >= rotateArray[index2]){
if(index2 == index1 + 1){
indexMid = index2;
break;
}
indexMid = index1 + (index2 - index1) / 2;
if(rotateArray[index1] == rotateArray[index2] &&
rotateArray[index1] == rotateArray[indexMid])
return minInorder(rotateArray, index1, index2);
if(rotateArray[index1] <= rotateArray[indexMid])
index1 = indexMid;
//else if(rotateArray[indexMid] <= rotateArray[index2])
else
index2 = indexMid;
}
return rotateArray[indexMid];
}
private:
int minInorder(vector<int> rotateArray, int index1, int index2){
int result = rotateArray[index1];
for(int i = index1 + 1; i <= index2; i++){
if(result < rotateArray[i])
result = rotateArray[i];
}
return result;
}
};
9.斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
思路: 用递归的话,会重复计算,所以用循环。此外可以根据公式减少循环次数,不过比较麻烦。
跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:其实就是斐波那契数列问题。
class Solution {
public:
int jumpFloor(int number) {
int fibOne = 0;
int fibTwo = 1;
int fibN;
if(number == 0) return 0;
for(int i = 1; i <= number; i++){
fibN = fibOne + fibTwo;
fibOne = fibTwo;
fibTwo = fibN;
}
return fibN;
}
};
变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:根据数学归纳法可以得知,跳法共有2^(n-1)种,根据位运算求得。
class Solution {
public:
int jumpFloorII(int number) {
int a = 1;
return a<<(number - 1);
}
};
矩阵覆盖
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思路:斐波那契数列问题
class Solution {
public:
int rectCover(int number) {
int fib1 = 1;
int fib2 = 2;
int fibN = 0;
if(number == 1 || number == 2) return number;
for(int i = 3; i <= number; i++){
fibN = fib1 + fib2;
fib1 = fib2;
fib2 = fibN;
}
return fibN;
}
};
10.二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:如果让该数右移与1做&运算会出现死循环,因为负数右移左边补1。
class Solution {
public:
int NumberOf1(int n) {
unsigned int flag = 1;
int count = 0;
while(flag){
if(n & flag) ++count;
flag = flag << 1;
}
return count;
}
};