我的目录:
环形链表的约瑟夫问题(进阶)
描述:
据说著名犹太历史学家 Josephus 有过以下故事:在罗马人占领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一种自杀方式,41 个人排成一个圆圈,由第 1 个人开始报数,报数到 3 的人就自杀,然后再由下一个人重新报 1,报数到 3 的人再自杀,这样依次下去,直到剩下最后一个人时,那个人可以自由选择自己的命运。这就是著名的约瑟夫问题。现在请用单向环形链表得出最终存活的人的编号。
输入描述:
一行两个整数 n,m,n 表示链表的长度,m 表示每报数到 m 就自杀。
输出描述:
输出最后存活的人的编号(编号从 1 开始到 n)。
给一个测试用例:
输入:
5 2
复制
输出:
3
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int People_live(int n, int m)
{
if (n == 1)//如果最后剩一个人
{
return 1;//返回最后存活的人
}
//链表的长度是:n = n - 1,报到m就自杀:m = m - 1
//返回新的长度=新的长度%旧得长度加1
return (People_live(n - 1, m) + m - 1) % n + 1;//递归
}
int main()
{
int n; int m;
scanf_s("%d%d", &n, &m);
printf("%d\n", People_live(n, m));
return 0;
}
VS验证一下:
计算二叉树左叶子之和
计算给定二叉树的所有左叶子之和。
示例1:
在这个二叉树中,有两个左叶子,分别是 8和 18,所以返回 26
示例2:
在这个二叉树中,没有左叶子,返回0
思路:本题的关键在于如何判断是不是左叶子?平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性,该题可以扩展大家对二叉树的解题思路。
具体方法为:判断父节点的左不为空,且父的左的左为空,且父的左的右为空。因此可以遍历整个二叉树,判断遍历到的每个节点node,判断该node是否满足如下条件,如果满足则将结果值加上该节点做子节点的值,接着再处理左子树和右子树。
此时问题已经转化成对二叉树的遍历了。顺便提一下,遍历可以分为深度优先和广度优先。
深度优先:前中后序遍历,可以使用递归和迭代两种方法,迭代使用栈。
广度优先:层序遍历,使用迭代方法,使用队列。
if(node->left && !node->left->left && !node->left->right)
result += node->left->val;
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(!root) return 0;
int result = 0;
queue<TreeNode*> que;
que.push(root);
while(que.size()){
int size = que.size();
for(int i = 0; i < size; i++){
TreeNode* node = que.front();
que.pop();
if(node->left && !node->left->left && !node->left->right)
result += node->left->val;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return result;
}
};