1.二维数组的查找
根据大小行列查找
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int n = array.size(),m = array[0].size();
int i = n-1,j = 0;
while(i >= 0 && j < m){
if(array[i][j] > target)
i--;
else if(array[i][j] < target)
j++;
else
return true;
}
return false;
}
};
2.替换空格
计算长度替换
class Solution {
public:
void replaceSpace(char *str,int length) {
if(str == NULL || length == 0)
return;
int len = 0;
for(int i = 0;str[i] != '\0';i++)
if(str[i] == ' ')
len++;
len = length + len*2;
for(;length >= 0 && len > length;length--){
if(str[length] == ' '){
str[len] = '0';str[--len] = '2';str[--len] = '%';
}
else
str[len] = str[length];
--len;
}
}
};
3.从尾到头打印链表
遍历
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> v;
while(head != NULL){
v.insert(v.begin(),head->val);
head = head->next;
}
return v;
}
};
4.重建二叉树
每颗子树的根结点肯定是先序遍历的第一个结点,根据先序遍历和中序遍历得到子树的遍历结果,利用递归思想不断的处理左右子树
/**
* 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> in) {
if(in.size() == 0)
return NULL;
TreeNode* head = new TreeNode(pre[0]);
vector<int> l_pre,l_in,r_pre,r_in;
int pos = 0;
for(int i = 0;i < in.size();i++)
if(in[i] == pre[0]){
pos = i;
break;
}
for(int i = 0;i < pos;i++){
l_pre.push_back(pre[i+1]);
l_in.push_back(in[i]);
}
for(int i = pos+1;i < in.size();i++){
r_pre.push_back(pre[i]);
r_in.push_back(in[i]);
}
head->left = reConstructBinaryTree(l_pre,l_in);
head->right = reConstructBinaryTree(r_pre,r_in);
return head;
}
};
5.用两个栈来实现队列
用栈1来存储,出队列的时候用栈2辅助
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
int t = stack2.top();
stack2.pop();
while(!stack2.empty()){
stack1.push(stack2.top());
stack2.pop();
}
return t;
}
private:
stack<int> stack1;
stack<int> stack2;
};
6.旋转数组的最小数字
根据其单调性
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.size() == 0)
return 0;
int pos = 0;
for(int i = 0;i < rotateArray.size();i++){
if(rotateArray[i] < rotateArray[pos])
return rotateArray[i];
pos = i;
}
return pos+1 < rotateArray.size() ? rotateArray[pos+1] : rotateArray[pos];
}
};
7.斐波那契数列
class Solution {
public:
int f[40] = {0,1};
int Fibonacci(int n) {
for(int i = 2;i <= n;i++)
f[i] = f[i-1] + f[i-2];
return f[n];
}
};
8.跳台阶
class Solution {
public:
int f[40] = {1,1};
int jumpFloor(int n) {
for(int i = 2;i <= n;i++)
f[i] = f[i-1] + f[i-2];
return f[n];
}
};
9.变态跳台阶
递推发现二倍规律
class Solution {
public:
int jumpFloorII(int n) {
if(n == 0 || n == 1) return 1;
int sum = 1;
while(--n)
sum <<= 1;
return sum;
}
};
10.矩阵覆盖
int a[100005]={0,1,2};
class Solution {
public:
int rectCover(int number) {
for(int i = 3;i <= number;i++)
a[i] = a[i-1] + a[i-2];
return a[number];
}
};
11.二进制中1的个数
class Solution {
public:
int NumberOf1(int n) {
int sum = 0;
while(n){
sum++;
n = n&(n-1);
}
return sum;
}
};
12.数值的整数次方
class Solution {
public:
double Power(double base, int exponent) {
double ans = 1.0;
int b = abs(exponent);
while(b > 0){
if(b&1)
ans = ans*base;
base = base*base;
b >>= 1;
}
if(exponent < 0)
return 1.0/ans;
return ans;
}
};
13.调整数组顺序使奇数位于偶数前面
先奇后偶
class Solution {
public:
void reOrderArray(vector<int> &array) {
int len = array.size();
vector<int> d;
for(int i = 0;i < len;i++)
if(array[i]&1)
d.push_back(array[i]);
for(int i = 0;i < len;i++)
if(array[i]%2 == 0)
d.push_back(array[i]);
array = d;
}
};
14.链表中倒数第k个结点
两个指针,p1比p2早走k个结点,p1=null,p2恰好为倒数第k个
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead == NULL)
return NULL;
ListNode *pFirst = pListHead;
for(int i = 0;i < k;i++){
if(pFirst == NULL)
return NULL;
pFirst = pFirst->next;
}
ListNode *pResult = pListHead;
while(pFirst != NULL){
pFirst = pFirst->next;
pResult = pResult->next;
}
return pResult;
}
};
15.反转链表
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL)
return NULL;
ListNode *pre = NULL,*cur = pHead,*nxt = NULL;
while(cur != NULL){
nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
};
16.合并两个排序的链表
还是递归更好写
递归:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL)
return pHead2;
if(pHead2 == NULL)
return pHead1;
ListNode *p = NULL;
if(pHead1->val <= pHead2->val)
p = pHead1,p->next = Merge(pHead1->next,pHead2);
else
p = pHead2,p->next = Merge(pHead1,pHead2->next);
return p;
}
};
非递归:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL)
return pHead2;
if(pHead2 == NULL)
return pHead1;
ListNode *p1 = pHead1,*p2 = pHead2;
ListNode *head = new ListNode(-1);
ListNode *p = NULL;
if(p1->val <= p2->val)
head = p = p1,p1 = p1->next;
else
head = p = p2,p2 = p2->next;
while(p1 != NULL && p2 != NULL){
if(p1->val <= p2->val)
p->next = p1,p = p->next,p1 = p1->next;
else
p->next = p2,p = p->next,p2 = p2->next;
}
if(p1 == NULL)
p->next = p2;
else
p->next = p1;
return head;
}
};
17.树的子结构
遍历A树的每个结点,判断从这个节点开始是否匹配B
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool isSubtree(TreeNode* p1,TreeNode* p2)
{
if(p1 == NULL && p2 != NULL)//A
return false;
if(p2 == NULL)//B匹配完毕
return true;
if(p1->val == p2->val)//继续匹配
return isSubtree(p1->left,p2->left) && isSubtree(p1->right,p2->right);
else
return false;
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot1 == NULL || pRoot2 == NULL)
return false;
return isSubtree(pRoot1,pRoot2) || HasSubtree(pRoot1->left,pRoot2) || HasSubtree(pRoot1->right,pRoot2);
}
};
18.二叉树的镜像
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void Mirror(TreeNode *pRoot) {
if(pRoot == NULL)
return;
TreeNode *temp = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = temp;
Mirror(pRoot->left);
Mirror(pRoot->right);
}
};
19.顺时针打印矩阵
打四个标记,注意避免重复打印
class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
vector<int> v;
int m = matrix.size(),n = matrix[0].size();
int left = 0,right = n-1,up = 0,down = m-1;
while(left <= right && up <= down){
for(int i = left;i <= right;i++)
v.push_back(matrix[up][i]);
for(int i = up+1;i <= down;i++)
v.push_back(matrix[i][right]);
if(up < down)
for(int i = right-1;i >= left;i--)
v.push_back(matrix[down][i]);
if(left < right)
for(int i = down-1;i > up;i--)
v.push_back(matrix[i][left]);
left++;
right--;
up++;
down--;
}
return v;
}
};
20.包含min函数的栈
多维护一个栈,保存当前栈内最小值
class Solution {
public:
stack<int> s,minS;
void push(int value) {
s.push(value);
if(minS.empty())
minS.push(value);
else{
if(minS.top() > value)
minS.push(value);
else
minS.push(minS.top());
}
}
void pop() {
if(!s.empty()){
s.pop();
minS.pop();
}
}
int top() {
if(!s.empty())
return s.top();
return 0;
}
int min() {
if(!minS.empty())
return minS.top();
return 0;
}
};
21.栈的压入、弹出序列
维护一个栈,不断将压入序列ai存入,如果和弹出序列bj相等,就pop(a[i]),j++,判断是否全部符合
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
stack<int> s;
int j = 0;
for(int i = 0;i < pushV.size();i++){
s.push(pushV[i]);
while(!s.empty() && s.top() == popV[j])
s.pop(),j++;
}
return s.empty();
}
};
22.从上往下打印二叉树
队列层次遍历
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
queue<TreeNode*> q;
if(root != NULL)
q.push(root);
vector<int> v;
while(!q.empty()){
TreeNode* f = q.front();
q.pop();
v.push_back(f->val);
if(f->left != NULL)
q.push(f->left);
if(f->right != NULL)
q.push(f->right);
}
return v;
}
};
23.二叉搜索树的后序遍历序列
递归:
根据二叉搜索树的特性,不断对左右子树和根比较
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.size() == 0)
return false;
int len = sequence.size();
return judge(0,len-1,sequence);
}
bool judge(int l,int r,vector<int> a){
if(l >= r)
return true;
int i = r-1;
while(i >= l && a[i] > a[r])
i--;
for(int j = i;j >= l;j--)
if(a[j] > a[r])
return false;
return judge(l,i,a) && judge(i+1,r-1,a);
}
};
比较巧妙地方式,看和根比较完是否包括了所有子结点
非递归:
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.size() == 0)
return false;
int len = sequence.size();
while(--len){
int i = 0;
while(sequence[i++] < sequence[len]);
while(sequence[i++] > sequence[len]);
if(i < len)
return false;
}
return true;
}
};
24.二叉搜索树的后序遍历序列
直接搜索
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<vector<int> > v;
vector<int> vec;
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
if(root == NULL)
return v;
vec.push_back(root->val);
if(expectNumber - root->val == 0 && root->left == NULL && root->right == NULL)
v.push_back(vec);
FindPath(root->left,expectNumber-root->val);
FindPath(root->right,expectNumber-root->val);
if(vec.size() != 0)
vec.pop_back();
return v;
}
};
25.复杂链表的复制
看懂这个图就会了,来源
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead == NULL)
return NULL;
//复制结点并且插入
RandomListNode *cur = pHead;
while(cur){
RandomListNode *newnode = new RandomListNode(cur->label);
newnode->next = cur->next;
cur->next = newnode;
cur = newnode->next;
}
//遍历链表,连接新表的random
cur = pHead;
while(cur){
RandomListNode *newnode = cur->next;
if(cur->random)//原结点有random
newnode->random = cur->random->next;
cur = newnode->next;
}
//拆链表得到新表
RandomListNode *pnewHead = pHead->next;
cur = pHead;
while(cur->next){
RandomListNode *temp = cur->next;
cur->next = cur->next->next;
cur = temp;
}
return pnewHead;
}
};
用map的区别不大,可以参考here
26.二叉搜索树与双向链表
由于是排序的双向链表,所以可以用中序遍历的方式遍历二叉搜索树,然后左指针指向下一个节点
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree == NULL)
return NULL;
TreeNode *pre = NULL;
inorder(pRootOfTree,pre);
TreeNode *res = pRootOfTree;
while(res->left)
res = res->left;
return res;
}
void inorder(TreeNode* root,TreeNode*& pre)
{
if(root == NULL)
return;
inorder(root->left,pre);
root->left = pre;
if(pre)
pre->right = root;
pre = root;
inorder(root->right,pre);
}
};
27.字符串的排列
枚举所有的情况
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> v;
if(str == "")
return v;
solve(str,0,v);
sort(v.begin(),v.end());
return v;
}
void solve(string str,int pos,vector<string> &v){
if(pos == str.length()){
v.push_back(str);
return;
}
for(int i = pos;str[i] != '\0';i++){
if(i != pos && str[pos] == str[i])
continue;
swap(str[pos],str[i]);
solve(str,pos+1,v);
swap(str[pos],str[i]);
}
}
};
28.数组中出现次数超过一半的数字
哈希
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
unordered_map<int,int> mp;
int n = numbers.size()/2;
for(int i = 0;i < numbers.size();i++){
mp[numbers[i]]++;
if(mp[numbers[i]] > n)
return numbers[i];
}
return 0;
}
};
巧妙的解法,如果数字x在数组中出现次数超过一半,那么去掉两个不同的数字,数字x在数组中出现次数仍然超过一半
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int count = 0,num = 0;
for(int i = 0;i < numbers.size();i++){
if(count == 0)
num = numbers[i],count = 1;
else{
if(num == numbers[i])
count++;
else
count--;
}
}
count = 0;
for(int i = 0;i < numbers.size();i++)
if(numbers[i] == num)
count++;
if(count > numbers.size()/2)
return num;
else
return 0;
}
};
和为S的连续正数序列
1.用两个指针枚举序列
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > v;
int l = 1,r = 1,cnt = 1;
while(l <= r && r < sum-1){
r++;
cnt += r;
while(cnt > sum){
cnt -= l;
l++;
}
if(cnt == sum){
vector<int> num;
for(int i = l;i <= r;i++)
num.push_back(i);
v.push_back(num);
}
}
return v;
}
};
2.利用序列是等差为1的等差数列,长度n为奇数的话,中间值(整数平均值)n=sum,所以sum%n==0;n为偶数n的话,整数平均值n+0.5n=sum,所以sum%n2==n;
n*(1+n)/2 = sum,求解n最大为
2
∗
s
u
m
\sqrt{2*sum}
2∗sum
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > v;
for(int n = (int)sqrt(sum*2);n >= 2;n--){
if(((n&1) && sum % n == 0) || (!(n&1) && sum%n*2 == n)){
vector<int> num;
for(int cnt = 0,i = sum/n - (n-1)/2;cnt < n;i++,cnt++)
num.push_back(i);
v.push_back(num);
}
}
return v;
}
};