11.二进制中1的个数
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
解题思路:
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响.
举例 : 60 111100
59 111011
count 1 60 & 59 = 111000
count 2 111000&(111000-1)=111000&(110111)=110000
count 3 110000&101111=100000
count 4 100000&011111=000000 end
class Solution {
public:
int NumberOf1(int n) {
if(n==0)
{
return 0;
}
int count=0;
while(n!=0)
{
count++;
n=n&(n-1);
}
return count;
}
};
12.数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
解题思路:
考虑 exponent 在0处的影响
使用快速幂算法 加速运算 使用三目运算符输出
在C语言中,power%2==1可以用更快的“位运算”来代替,例如:power&1。因为如果power为偶数,则其二进制表示的最后一位一定是0;如果power是奇数,则其二进制表示的最后一位一定是1。将他们分别与1的二进制做“与”运算,得到的就是power二进制最后一位的数字了,是0则为偶数,是1则为奇数。例如5是奇数,则5&1=1;而6是偶数,则6&1=0;因此奇偶数的判断就可以用“位运算”来替换了
同样,对于power=power/2来说,也可以用更快的“位运算”进行替代,我们只要把power的二进制表示向右移动1位就能变成原来的一半了。
class Solution {
public:
double Power(double base, int exponent) {
int n=abs(exponent);
double result =1.0;
if(base==0){
return 0.0;
}
if(exponent==0)
{
return 1.0;
}
while(n!=0)
{
if(n&1)
{
result*=base;
}
base=base*base;
n=n>>1;
}
return exponent>0?result:1/result;
}
};
13.调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解题思路1:
借鉴插入排序的思想 设置j k两个指针 k指针计算奇数个数 j指针遍历奇数 设置循环终止条件 由于j指针比k指针快一个字节 若缺少 j-- 循环无法弹出
class Solution {
public:
void reOrderArray(vector<int> &array) {
int len =array.size();
int k=0 ;//奇数个数计数 并与j组成快慢指针
for(int i=0;i<len;i++)
{
if(array[i]&1==1)
{
int j=i;
while(j>k)
{
swap(array[j],array[j-1]);
j--;
}
k++;
}
}
}
};
解题思路2:
不使用排序 直接new一个新数组 然后遍历出奇数 并将其放入新数组 最后遍历剩下的放入新数组
class Solution {
public:
void reOrderArray(vector<int> &array) {
vector<int> temp;
for(int i=0;i<array.size();i++)
{
if(array[i]%2==1)
{
temp.push_back(array[i]);
}
}
for(int i=0;i<array.size();i++)
{
if(array[i]%2==0)
{
temp.push_back(array[i]);
}
}
array=temp;
}
};
14.链表中倒数第k个结点
输入一个链表,输出该链表中倒数第k个结点。
解题思路:
使用快慢指针 fast指针 先跑 k 个节点 然后 fast slow一起跑 当fast跑到尾时 slow跑到倒数第k个
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==nullptr||k<1)
{
return nullptr;
}
ListNode* slow=pListHead;
ListNode* fast=pListHead;
while(k>0)
{
if(fast==nullptr)
{
return nullptr;
}
fast=fast->next;
k--;
}
while(fast!=nullptr)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
};
15.反转链表
输入一个链表,反转链表后,输出新链表的表头。
解题思路:
做的时候可以画图 解析
使用两个指针 一个指向头节点 一个指向下一个节点 在断开链接时需要 保存下一个节点 其实可以算作三个指针 然后整体三个指针后移
若第一个指针为头节点 则 修改方向后 需要指向nullptr
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead==nullptr||pHead->next==NULL)
{
return pHead;
}
ListNode *pcur=pHead;
ListNode *pnext=pHead->next;
ListNode *pnenext;
while(pnext!=nullptr)
{
pnenext=pnext->next;
pnext->next=pcur;
if(pcur==pHead)
{
pcur->next=nullptr;
}
pcur=pnext;
pnext=pnenext;
}
return pcur;
}
};
16.合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
解题思路:
类似于归并排序思路 利用while和递归完成merge
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1==nullptr)
{
return pHead2;
}
if(pHead2==nullptr)
{
return pHead1;
}
ListNode* newhead=nullptr;
if(pHead1->val<=pHead2->val)
{
newhead=pHead1;
newhead->next=Merge(pHead1->next,pHead2);
}
else{
newhead=pHead2;
newhead->next=Merge(pHead1,pHead2->next);
}
return newhead;
}
};
17.树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
解题思路:
递归解题 思路 是先判断根节点 是否满足条件 然后 判断 左右子树是否判断条件 然后 在满足条件时 进入判断包含的函数 此时先思考 如何判断 条件为 左右节点全部相等 然后思考退出条件
class Solution {
public:
bool istrue(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2==nullptr)
{
return true;
}
if(pRoot1==nullptr)
{
return false;
}
if(pRoot1->val!=pRoot2->val)
{
return false;
}
return istrue(pRoot1->left,pRoot2->left)&& istrue(pRoot1->right,pRoot2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool result =false;
if(pRoot1&&pRoot2!=nullptr)
{
if(pRoot1->val==pRoot2->val)
{
result = istrue(pRoot1,pRoot2);
}
if(!result)
{
result=HasSubtree(pRoot1->left,pRoot2);
}
if(!result)
{
result=HasSubtree(pRoot1->right,pRoot2);
}
}
return result;
}
};
18.二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zEijsPrz-1596962618354)(C:\Users\ian\AppData\Roaming\Typora\typora-user-images\image-20200809153228481.png)]
解题思路:
递归思路 先思考结果 再思考如何写
class Solution {
public:
void reversetree(TreeNode *pRoot)
{
if(pRoot==nullptr)
{
return ;
}
swap(pRoot);
reversetree(pRoot->left);
reversetree(pRoot->right);
}
void swap(TreeNode *pRoot)
{
TreeNode *temp=nullptr;
temp=pRoot->left;
pRoot->left=pRoot->right;
pRoot->right=temp;
}
void Mirror(TreeNode *pRoot) {
reversetree(pRoot);
}
};
19.顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
解题思路:
四个变量 表示矩阵四个角 注意边界 和只有一行会重复打印
class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
vector<int> res;
int row=matrix.size();
int col=matrix[0].size();
if(row==0||col==0)
{
return res;
}
int left =0; int right =col-1;
int top =0; int down =row-1;
while(left<=right&&top<=down){
for(int i=left;i<=right;i++)
{
res.push_back(matrix[top][i]);
}
for(int i=top+1;i<=down;i++)
{
res.push_back(matrix[i][right]);
}
if(top!=down){
for(int i=right-1;i>=left;i--)
{
res.push_back(matrix[down][i]);
}
}
if(left!=right){
for(int i=down-1;i>top;i--)
{
res.push_back(matrix[i][left]);
}
}
left++;right--;top++;down--;
}
return res;
}
};
20.包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
解题思路:
使用辅助栈 ,所有元素都进入辅助栈 ,当接受最小元素,若入栈元素小于最小函数栈元素 ,则入最小函数栈 ; 弹出时,若两栈顶不一样则弹出辅助栈 否则弹出最小函数栈 top则为辅助栈顶 min则为最小函数栈顶
class Solution {
public:
stack<int> stk;
stack<int> stk_min;
void push(int value) {
stk.push(value);
if(stk_min.empty())
{
stk_min.push(value);
}
else{
if(value<stk_min.top())
{
stk_min.push(value);
}
}
}
void pop() {
if(stk.top()==stk_min.top())
{
stk_min.pop();
}
stk.pop();
}
int top() {
return stk.top();
}
int min() {
return stk_min.top();
}
};