《剑指offer》JZ11 ~ JZ20
Posted 黑桃️
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《剑指offer》JZ11 ~ JZ20相关的知识,希望对你有一定的参考价值。
《剑指offer》JZ11 ~ JZ20
JZ11:二进制中1的个数
开始使用的不断&1,发现负数有点问题,然后学到了以下方法。
n & (n-1) 可以去除n的二进制表示中最右边的一个1,n-1可将二进制中最右边一个1变为0,其右边位的数变为1。然后再与原来的n进行&操作,1&0=0,0&1=0,所以变化的部分全部变为0.
class Solution {
public:
int NumberOf1(int n) {
int ans=0;
while(n)
{
// 去除n的二进制表示中最右边的一个1
n=n&(n-1);
ans++;
}
return ans;
}
};
JZ12:数值的整数次方
经典的快速幂,负数次方幂的情况:先求正次方幂然后求倒数即可。例如2-2=1 / 22
class Solution {
public:
double Power(double base, int exponent) {
// 先用正数幂求
int n=abs(exponent);
double ans=1;
while(n)
{
if(n&1) ans*=base;
base*=base;
n>>=1;
}
// 负数处理
if(exponent<0) ans=1/ans;
return ans;
}
};
JZ13:调整数组顺序使奇数位于偶数前面
直接把奇数和偶数分离,然后把偶数放在奇数后面。没考虑什么更sao的写法
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型vector
* @return int整型vector
*/
vector<int> reOrderArray(vector<int>& array) {
// write code here
vector<int> m,n;
for(int i=0;i<array.size();i++)
{
// 奇数和偶数分别放入不同的vector
if(array[i]%2) m.push_back(array[i]);
else n.push_back(array[i]);
}
// 把偶数放在奇数后面
for(int i=0;i<n.size();i++)
m.push_back(n[i]);
return m;
}
};
JZ14:链表中倒数最后k个结点
前后指针,让后指针先走k步,然后前后指针一起往后走,那么当后指针走完链表,前指针所指的位置正好是倒数第k个。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
ListNode* pr = pHead;
// 后指针先走k步
while(k--)
{
if(pr==NULL) return pr;
pr=pr->next;
}
// 前后指针一起往后走,直到后指针走完,前指针就是倒数第k
while(pr)
{
pr=pr->next;
pHead=pHead->next;
}
return pHead;
}
};
JZ15:反转链表
原地反转,和下面blog不同的是,该种情况应该是没有头结点的那种
相关博客
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode* p = pHead;
ListNode* q = NULL;
ListNode* t;
while(p)
{
t = p->next;
p->next = q;
q = p;
p = t;
}
return q;
}
};
JZ16:合并两个排序的链表
俩链表都从头开始比较,小的节点就先合并,然后指针往后移,直到某一条链表比完了,那么另一条剩下的节点(一定更大)就可以直接合并
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
// 头节点
ListNode* head = new ListNode(-1);
ListNode* p = head;
ListNode* q;
while(pHead1 && pHead2)
{
// pHead2的节点小,先合并pHead2的该节点,指针后移
if(pHead1->val >= pHead2->val)
{
q = new ListNode(pHead2->val);
pHead2 = pHead2->next;
}
else if(pHead1->val < pHead2->val)
{
q = new ListNode(pHead1->val);
pHead1 = pHead1->next;
}
p->next = q;
p = q;
}
// 哪条剩下就直接合并剩下的
if(pHead1) p->next = pHead1;
if(pHead2) p->next = pHead2;
return head->next;
}
};
JZ17:树的子结构
两个递归,HasSubtree遍历pRoot1的各个部分与pRoot2进行比较,pan中比较pRoot1,pRoot2是否完全一致
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
if(pRoot2==NULL || pRoot1==NULL) return false;
// 根相同(也可以不写,pan里面也会比较),且比较为true
if(pRoot2->val==pRoot1->val && pan(pRoot1,pRoot2)) return true;
// 走左子树和右子树
else return HasSubtree(pRoot1->left, pRoot2) || HasSubtree(pRoot1->right, pRoot2);
}
// 递归比较
bool pan(TreeNode* t1, TreeNode* t2)
{
// t2都比完了(代表前面都相同)就返回true
if(t2 == NULL) return true;
if(t1 == NULL || t1->val!=t2->val) return false;
return pan(t1->left,t2->left) && pan(t1->right,t2->right);
}
};
JZ18:二叉树的镜像
递归,从上到下交换所有的左右子树
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pRoot TreeNode类
* @return TreeNode类
*/
TreeNode* Mirror(TreeNode* pRoot) {
// write code here
if(!pRoot) return NULL;
// 临时节点t,交换左右子树
TreeNode* t = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = t;
// 往下走,以左右子为根继续交换左右子树
Mirror(pRoot->left);
Mirror(pRoot->right);
return pRoot;
}
};
JZ19: 顺时针打印矩阵
模拟,不断以 右下左上 的方向走,直到所有点都走完,思路不难,细节需要注意,容易出错
class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
vector<int> ans;
// 记录每个点是否走过
bool vis[100][100]={0};
// 当前所在点(x,y)
int x=0,y=0;
while(1)
{
// 右,未出界且未走过
while(y+1<matrix[0].size() && !vis[x][y+1])
{
ans.push_back(matrix[x][y]);
vis[x][y++]=1;
}
while(x+1<matrix.size() && !vis[x+1][y])
{
ans.push_back(matrix[x][y]);
vis[x++][y]=1;
}
while(y-1>=0 && !vis[x][y-1])
{
ans.push_back(matrix[x][y]);
vis[x][y--]=1;
}
while(x-1>=0 && !vis[x-1][y])
{
ans.push_back(matrix[x][y]);
vis[x--][y]=1;
}
// 每次转方向前不会标记位置,所以最后一个点此时没被标记,所以是-1
if(ans.size() == matrix.size()*matrix[0].size()-1)
{
// 放入最后一个点
ans.push_back(matrix[x][y]);
break;
}
}
return ans;
}
};
JZ20:包含min函数的栈
一个栈用来push,另一个用来记录每次push后栈的最小值
class Solution {
public:
stack<int> s,m;
void push(int value) {
s.push(value);
// 栈为空时,最小值就是刚加入的value
if(m.empty()) m.push(value);
else{
// 和栈顶(记录之前的最小值)比,看谁更小
if(value > m.top()) m.push(m.top());
else m.push(value);
}
}
void pop() {
m.pop();
s.pop();
}
int top() {
return s.top();
}
int min() {
return m.top();
}
};
以上是关于《剑指offer》JZ11 ~ JZ20的主要内容,如果未能解决你的问题,请参考以下文章
牛客网剑指offer专题python解答JZ1---JZ12持续刷题中
牛客网剑指offer专题python解答JZ1---JZ12持续刷题中