面试题打卡——C++版
Posted ych9527
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题打卡——C++版相关的知识,希望对你有一定的参考价值。
旋转链表
题解:
给你一个链表的头节点 head
,旋转链表,将链表每个节点向右移动 k
个位置。
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(head==nullptr||head->next==nullptr)//没有或者只有一个节点
return head;
int len=0;
ListNode *cur=head;
while(cur)//求出链表长度
{
len++;
cur=cur->next;
}
k%=len;
k=len-k;
cur=head;
ListNode* prev=nullptr;
while(k--)
{
prev=cur;
cur=cur->next;
}
prev->next=nullptr;
ListNode* newhead=cur;
if(cur==nullptr)//此时k==0
return head;
while(cur->next)//将旧的头链接在新的头后面
{
cur=cur->next;
}
cur->next=head;
return newhead;
}
};
二叉搜索树中第K小的元素
给定一个二叉搜索树的根节点 root
,和一个整数 k
,请你设计一个算法查找其中第 k
个最小元素(从 1 开始计数)。
题解:
1.二叉搜索树的中序遍历得到的结果之中,是升序的,求第k个最小的元素,则需输出第k个数即可
2.将K值传引用进入递归函数,中序遍历二叉树
3.每访问一个节点 k–,当k==0时说明,此时访问的节点,即所求节点,用过引用返回值拿出来即可
class Solution {
public:
void _kthSmallest(TreeNode* root,int &k,int &val)
{
if(root==nullptr||val!=-1)
return ;
_kthSmallest(root->left,k,val);
k--;
if(k==0)
{
val=root->val;
return ;
}
_kthSmallest(root->right,k,val);
}
int kthSmallest(TreeNode* root, int k) {
int val=-1;
_kthSmallest(root,k,val);
return val;
}
};
Nim游戏
你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头。你们轮流进行自己的回合,你作为先手。每一回合,轮到的人拿掉 1 - 3 块石头。拿掉最后一块石头的人就是获胜者。假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢,返回 true;否则,返回 false 。
题解:
1.当n<=3时,直接全部拿走,即可以获得胜利
2.当 n>3时,此时我们需要保证倒数第二轮的时候,剩下的石块的个数正好是4块,并且是对方拿.
这是因为如果倒数第二轮的时候剩下的是4块石头,那么对方一次是拿不完的,并且自己在下一次就可以将全部石块拿完,取得胜利
3.由第2点知晓,我们要保证倒数第二轮是对方拿,并且石块数量是4块,那么这一条件如何实现呢?
只要第一次拿完之后,剩下的石块是4的倍数既可以实现了。 这是因为,第一次拿完,剩下的是4的倍数,不管对方拿多少块,下一次自己拿的时候,只需要将剩余的石块的数量保持为4的倍数即可
class Solution {
public:
bool canWinNim(int n) {
//如果想要赢,需要保证倒数第二次的石块数量为4块,并且是对方拿
//-> 因为不论对方拿几块,自己都可以取得最后的石块
//第一次自己拿,拿完之后,如果能够保证剩下的石块为4的倍数,即可以获得胜利
if(n<=3)
return true;
for(int i=1;i<=3;i++)
{
if((n-i)%4==0)//为4的倍数
return true;
}
return false;
}
};
链表中的节点每k个一组翻转
将给出的链表中的节点每\\ k k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是\\ k k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
要求空间复杂度 \\ O(1) O(1)
题解:
ListNode *reverse(ListNode *head)//链表逆转
{
if(head==nullptr||head->next==nullptr)
return head;
ListNode *newhead=reverse(head->next);
head->next->next=head;
head->next=nullptr;
return newhead;
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(head==nullptr||k==0||head->next==nullptr)
return head;
vector<ListNode*>arr;//保存每个反转后的头结点
ListNode *prev=head;
ListNode *cur=head;
while(cur)
{
int count=1;
while(cur&&count!=k)
{
cur=cur->next;
count++;//来到翻转点
}
ListNode *next=nullptr;//保存下一个头结点
if(cur!=nullptr)//进行翻转
{
next=cur->next;//保存下一个节点
cur->next=nullptr;
arr.push_back(reverse(prev));//将翻转后的头结点保存起来
prev=cur=next;//进行更新
}
else//剩余节点不够了,不进行反转
{
arr.push_back(prev);
break;
}
}
//进行链表的链接
ListNode* rethead=arr[0];//返回的链表的头
cur = rethead;
for(int i=1;i<arr.size();i++)
{
ListNode *temp=arr[i];
while(cur->next)//走到当前链表的末尾
{
cur=cur->next;
}
cur->next=temp;//将链表链接起来
cur=temp;//更新链表的头
}
return rethead;
}
};
数组中相加和为0的三元组
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
注意:
- 三元组(a、b、c)中的元素必须按非降序排列。(即a≤b≤c)
- 解集中不能包含重复的三元组。
题解:
1.对数组排升序
2.构建for循环,从数组中,一次选取值作为 “起始值”
3.由与数组是升序的,因此当num[i] > 0时,直接退出循环 -> 最小的值都大于0了
4.给定两个指针left、right left的位置位于 i+1 right的位于 num.size()-1
5.sum=num[i]+num[left]+num[right]
sum==0时,说明以num[i]为最小值,找到了一个组合 ,此时更新left+1,如果num[left]==num[left-1] ,则继续更新(去重)
sum>0时,总体的值太大了right–
sum<0时,总体的值太小了 left++
6.第5点的循环结束后,说明,以num[i]为最小值的所有组合已经找出来了,继续更新最小值,遇到相同的则直接跳过
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
//先排序,然后选取中心点,再用双指针进行获取内容
vector<vector<int>>ret;
sort(num.begin(),num.end());
for(int i=0;i<num.size();i++)
{
if(i>0&&num[i-1]==num[i])//重复的中心点
continue;
if(num[i]>0)
break;//最小值都大于0
//给定中心点的两个指针
int left=i+1;
int right=num.size()-1;
while(left<right)
{
int sum=num[left]+num[i]+num[right];
if(sum==0)
{
vector<int>temp;
temp.push_back(num[i]);
temp.push_back(num[left]);
temp.push_back(num[right]);
ret.push_back(temp);
//换到新的位置
left++;
while(left<right&&num[left]==num[left-1])//同样的值
left++;
}
else if(sum>0)
right--;
else
left++;
}
}
return ret;
}
};
以上是关于面试题打卡——C++版的主要内容,如果未能解决你的问题,请参考以下文章